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.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 #ifndef BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED
10 
11 #include <boost/config.hpp>                             // SFINAE.
12 #include <boost/iostreams/concepts.hpp>
13 #include <boost/iostreams/categories.hpp>
14 #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
15 #include <boost/iostreams/detail/call_traits.hpp>
16 #include <boost/iostreams/detail/char_traits.hpp>
17 #include <boost/iostreams/detail/dispatch.hpp>
18 #include <boost/iostreams/detail/error.hpp>
19 #include <boost/iostreams/detail/streambuf.hpp>        // pubsync.
20 #include <boost/iostreams/detail/config/unreachable_return.hpp>
21 #include <boost/iostreams/device/null.hpp>
22 #include <boost/iostreams/traits.hpp>
23 #include <boost/iostreams/operations.hpp>
24 #include <boost/mpl/if.hpp>
25 #include <boost/static_assert.hpp>
26 #include <boost/throw_exception.hpp>
27 
28 // Must come last.
29 #include <boost/iostreams/detail/config/disable_warnings.hpp>  // MSVC.
30 
31 
32 namespace boost { namespace iostreams { namespace detail {
33 
34 template<typename Category> struct device_wrapper_impl;
35 template<typename Category> struct flt_wrapper_impl;
36 
37 template<typename T>
38 class concept_adapter {
39 private:
40     typedef typename detail::value_type<T>::type       value_type;
41     typedef typename dispatch<T, input, output>::type  input_tag;
42     typedef typename dispatch<T, output, input>::type  output_tag;
43     typedef typename
44             mpl::if_<
45                 is_device<T>,
46                 device_wrapper_impl<input_tag>,
47                 flt_wrapper_impl<input_tag>
48             >::type                                    input_impl;
49     typedef typename
50             mpl::if_<
51                 is_device<T>,
52                 device_wrapper_impl<output_tag>,
53                 flt_wrapper_impl<output_tag>
54             >::type                                    output_impl;
55     typedef typename
56             mpl::if_<
57                 is_device<T>,
58                 device_wrapper_impl<any_tag>,
59                 flt_wrapper_impl<any_tag>
60             >::type                                    any_impl;
61 public:
62     typedef typename char_type_of<T>::type             char_type;
63     typedef typename category_of<T>::type              category;
64 
concept_adapter(const reference_wrapper<T> & ref)65     explicit concept_adapter(const reference_wrapper<T>& ref) : t_(ref.get())
66     { BOOST_STATIC_ASSERT(is_std_io<T>::value); }
concept_adapter(const T & t)67     explicit concept_adapter(const T& t) : t_(t)
68     { BOOST_STATIC_ASSERT(!is_std_io<T>::value); }
69 
operator *()70     T& operator*() { return t_; }
operator ->()71     T* operator->() { return &t_; }
72 
read(char_type * s,std::streamsize n)73     std::streamsize read(char_type* s, std::streamsize n)
74     { return this->read(s, n, (basic_null_source<char_type>*) 0); }
75 
76     template<typename Source>
read(char_type * s,std::streamsize n,Source * src)77     std::streamsize read(char_type* s, std::streamsize n, Source* src)
78     { return input_impl::read(t_, src, s, n); }
79 
write(const char_type * s,std::streamsize n)80     std::streamsize write(const char_type* s, std::streamsize n)
81     { return this->write(s, n, (basic_null_sink<char_type>*) 0); }
82 
83     template<typename Sink>
write(const char_type * s,std::streamsize n,Sink * snk)84     std::streamsize write(const char_type* s, std::streamsize n, Sink* snk)
85     { return output_impl::write(t_, snk, s, n); }
86 
seek(stream_offset off,BOOST_IOS::seekdir way,BOOST_IOS::openmode which)87     std::streampos seek( stream_offset off, BOOST_IOS::seekdir way,
88                          BOOST_IOS::openmode which )
89     {
90         return this->seek( off, way, which,
91                            (basic_null_device<char_type, seekable>*) 0);
92     }
93 
94     template<typename Device>
seek(stream_offset off,BOOST_IOS::seekdir way,BOOST_IOS::openmode which,Device * dev)95     std::streampos seek( stream_offset off, BOOST_IOS::seekdir way,
96                          BOOST_IOS::openmode which, Device* dev )
97     { return any_impl::seek(t_, dev, off, way, which); }
98 
close(BOOST_IOS::openmode which)99     void close(BOOST_IOS::openmode which)
100     { this->close(which, (basic_null_device<char_type, seekable>*) 0); }
101 
102     template<typename Device>
close(BOOST_IOS::openmode which,Device * dev)103     void close(BOOST_IOS::openmode which, Device* dev)
104     { any_impl::close(t_, dev, which); }
105 
106     template<typename Device>
flush(Device * dev)107     bool flush( Device* dev )
108     {
109         bool result = any_impl::flush(t_, dev);
110         if (dev && dev->BOOST_IOSTREAMS_PUBSYNC() == -1)
111             result = false;
112         return result;
113     }
114 
115     template<typename Locale> // Avoid dependency on <locale>
imbue(const Locale & loc)116     void imbue(const Locale& loc) { iostreams::imbue(t_, loc); }
117 
optimal_buffer_size() const118     std::streamsize optimal_buffer_size() const
119     { return iostreams::optimal_buffer_size(t_); }
120 public:
121     concept_adapter& operator=(const concept_adapter&);
122     value_type t_;
123 };
124 
125 //------------------Specializations of device_wrapper_impl--------------------//
126 
127 template<>
128 struct device_wrapper_impl<any_tag> {
129     template<typename Device, typename Dummy>
130     static std::streampos
seekboost::iostreams::detail::device_wrapper_impl131     seek( Device& dev, Dummy*, stream_offset off,
132           BOOST_IOS::seekdir way, BOOST_IOS::openmode which )
133     {
134         typedef typename category_of<Device>::type category;
135         return seek(dev, off, way, which, category());
136     }
137 
138     template<typename Device>
139     static std::streampos
seekboost::iostreams::detail::device_wrapper_impl140     seek( Device&, stream_offset, BOOST_IOS::seekdir,
141           BOOST_IOS::openmode, any_tag )
142     {
143         boost::throw_exception(cant_seek());
144         BOOST_IOSTREAMS_UNREACHABLE_RETURN(0)
145     }
146 
147     template<typename Device>
148     static std::streampos
seekboost::iostreams::detail::device_wrapper_impl149     seek( Device& dev, stream_offset off,
150           BOOST_IOS::seekdir way, BOOST_IOS::openmode which,
151           random_access )
152     {
153         return iostreams::seek(dev, off, way, which);
154     }
155 
156     template<typename Device, typename Dummy>
closeboost::iostreams::detail::device_wrapper_impl157     static void close(Device& dev, Dummy*, BOOST_IOS::openmode which)
158     { iostreams::close(dev, which); }
159 
160     template<typename Device, typename Dummy>
flushboost::iostreams::detail::device_wrapper_impl161     static bool flush(Device& dev, Dummy*)
162     { return iostreams::flush(dev); }
163 };
164 
165 
166 template<>
167 struct device_wrapper_impl<input> : device_wrapper_impl<any_tag>  {
168     template<typename Device, typename Dummy>
169     static std::streamsize
readboost::iostreams::detail::device_wrapper_impl170     read( Device& dev, Dummy*, typename char_type_of<Device>::type* s,
171           std::streamsize n )
172     { return iostreams::read(dev, s, n); }
173 
174     template<typename Device, typename Dummy>
175     static std::streamsize
writeboost::iostreams::detail::device_wrapper_impl176     write( Device&, Dummy*, const typename char_type_of<Device>::type*,
177            std::streamsize )
178     { boost::throw_exception(cant_write());
179       BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
180 };
181 
182 template<>
183 struct device_wrapper_impl<output> {
184     template<typename Device, typename Dummy>
185     static std::streamsize
readboost::iostreams::detail::device_wrapper_impl186     read(Device&, Dummy*, typename char_type_of<Device>::type*, std::streamsize)
187     { boost::throw_exception(cant_read());
188       BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
189 
190     template<typename Device, typename Dummy>
191     static std::streamsize
writeboost::iostreams::detail::device_wrapper_impl192     write( Device& dev, Dummy*, const typename char_type_of<Device>::type* s,
193            std::streamsize n )
194     { return iostreams::write(dev, s, n); }
195 };
196 
197 //------------------Specializations of flt_wrapper_impl--------------------//
198 
199 template<>
200 struct flt_wrapper_impl<any_tag> {
201     template<typename Filter, typename Device>
202     static std::streampos
seekboost::iostreams::detail::flt_wrapper_impl203     seek( Filter& f, Device* dev, stream_offset off,
204           BOOST_IOS::seekdir way, BOOST_IOS::openmode which )
205     {
206         typedef typename category_of<Filter>::type category;
207         return seek(f, dev, off, way, which, category());
208     }
209 
210     template<typename Filter, typename Device>
211     static std::streampos
seekboost::iostreams::detail::flt_wrapper_impl212     seek( Filter&, Device*, stream_offset,
213           BOOST_IOS::seekdir, BOOST_IOS::openmode, any_tag )
214     { boost::throw_exception(cant_seek());
215       BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
216 
217     template<typename Filter, typename Device>
218     static std::streampos
seekboost::iostreams::detail::flt_wrapper_impl219     seek( Filter& f, Device* dev, stream_offset off,
220           BOOST_IOS::seekdir way, BOOST_IOS::openmode which,
221           random_access tag )
222     {
223         typedef typename category_of<Filter>::type category;
224         return seek(f, dev, off, way, which, tag, category());
225     }
226 
227     template<typename Filter, typename Device>
228     static std::streampos
seekboost::iostreams::detail::flt_wrapper_impl229     seek( Filter& f, Device* dev, stream_offset off,
230           BOOST_IOS::seekdir way, BOOST_IOS::openmode,
231           random_access, any_tag )
232     { return f.seek(*dev, off, way); }
233 
234     template<typename Filter, typename Device>
235     static std::streampos
seekboost::iostreams::detail::flt_wrapper_impl236     seek( Filter& f, Device* dev, stream_offset off,
237           BOOST_IOS::seekdir way, BOOST_IOS::openmode which,
238           random_access, two_sequence )
239     { return f.seek(*dev, off, way, which);  }
240 
241     template<typename Filter, typename Device>
closeboost::iostreams::detail::flt_wrapper_impl242     static void close(Filter& f, Device* dev, BOOST_IOS::openmode which)
243     { iostreams::close(f, *dev, which); }
244 
245     template<typename Filter, typename Device>
flushboost::iostreams::detail::flt_wrapper_impl246     static bool flush(Filter& f, Device* dev)
247     { return iostreams::flush(f, *dev); }
248 };
249 
250 template<>
251 struct flt_wrapper_impl<input> {
252     template<typename Filter, typename Source>
253     static std::streamsize
readboost::iostreams::detail::flt_wrapper_impl254     read( Filter& f, Source* src, typename char_type_of<Filter>::type* s,
255           std::streamsize n )
256     { return iostreams::read(f, *src, s, n); }
257 
258     template<typename Filter, typename Sink>
259     static std::streamsize
writeboost::iostreams::detail::flt_wrapper_impl260     write( Filter&, Sink*, const typename char_type_of<Filter>::type*,
261            std::streamsize )
262     { boost::throw_exception(cant_write());
263       BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
264 };
265 
266 template<>
267 struct flt_wrapper_impl<output> {
268     template<typename Filter, typename Source>
269     static std::streamsize
readboost::iostreams::detail::flt_wrapper_impl270     read(Filter&, Source*, typename char_type_of<Filter>::type*,std::streamsize)
271     { boost::throw_exception(cant_read());
272       BOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
273 
274     template<typename Filter, typename Sink>
275     static std::streamsize
writeboost::iostreams::detail::flt_wrapper_impl276     write( Filter& f, Sink* snk, const typename char_type_of<Filter>::type* s,
277            std::streamsize n )
278     { return iostreams::write(f, *snk, s, n); }
279 };
280 
281 //----------------------------------------------------------------------------//
282 
283 } } } // End namespaces detail, iostreams, boost.
284 
285 #include <boost/iostreams/detail/config/enable_warnings.hpp>  // MSVC.
286 
287 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED
288