blob: d182bee6b175d5813f1c0207b8f5b1a3081719dd [file] [log] [blame]
Jeff Thompson86b6d642013-10-17 15:01:56 -07001// (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 NDNBOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED
9#define NDNBOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED
10
11#include <ndnboost/config.hpp> // SFINAE.
12#include <ndnboost/iostreams/concepts.hpp>
13#include <ndnboost/iostreams/categories.hpp>
14#include <ndnboost/iostreams/detail/adapter/non_blocking_adapter.hpp>
15#include <ndnboost/iostreams/detail/call_traits.hpp>
16#include <ndnboost/iostreams/detail/char_traits.hpp>
17#include <ndnboost/iostreams/detail/dispatch.hpp>
18#include <ndnboost/iostreams/detail/error.hpp>
19#include <ndnboost/iostreams/detail/streambuf.hpp> // pubsync.
20#include <ndnboost/iostreams/detail/config/unreachable_return.hpp>
21#include <ndnboost/iostreams/device/null.hpp>
22#include <ndnboost/iostreams/traits.hpp>
23#include <ndnboost/iostreams/operations.hpp>
24#include <ndnboost/mpl/if.hpp>
25#include <ndnboost/static_assert.hpp>
26#include <ndnboost/throw_exception.hpp>
27
28// Must come last.
29#include <ndnboost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
30
31
32namespace ndnboost { namespace iostreams { namespace detail {
33
34template<typename Category> struct device_wrapper_impl;
35template<typename Category> struct flt_wrapper_impl;
36
37template<typename T>
38class concept_adapter {
39private:
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;
61public:
62 typedef typename char_type_of<T>::type char_type;
63 typedef typename category_of<T>::type category;
64
65 explicit concept_adapter(const reference_wrapper<T>& ref) : t_(ref.get())
66 { NDNBOOST_STATIC_ASSERT(is_std_io<T>::value); }
67 explicit concept_adapter(const T& t) : t_(t)
68 { NDNBOOST_STATIC_ASSERT(!is_std_io<T>::value); }
69
70 T& operator*() { return t_; }
71 T* operator->() { return &t_; }
72
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>
77 std::streamsize read(char_type* s, std::streamsize n, Source* src)
78 { return input_impl::read(t_, src, s, n); }
79
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>
84 std::streamsize write(const char_type* s, std::streamsize n, Sink* snk)
85 { return output_impl::write(t_, snk, s, n); }
86
87 std::streampos seek( stream_offset off, NDNBOOST_IOS::seekdir way,
88 NDNBOOST_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>
95 std::streampos seek( stream_offset off, NDNBOOST_IOS::seekdir way,
96 NDNBOOST_IOS::openmode which, Device* dev )
97 { return any_impl::seek(t_, dev, off, way, which); }
98
99 void close(NDNBOOST_IOS::openmode which)
100 { this->close(which, (basic_null_device<char_type, seekable>*) 0); }
101
102 template<typename Device>
103 void close(NDNBOOST_IOS::openmode which, Device* dev)
104 { any_impl::close(t_, dev, which); }
105
106 template<typename Device>
107 bool flush( Device* dev )
108 {
109 bool result = any_impl::flush(t_, dev);
110 if (dev && dev->NDNBOOST_IOSTREAMS_PUBSYNC() == -1)
111 result = false;
112 return result;
113 }
114
115 template<typename Locale> // Avoid dependency on <locale>
116 void imbue(const Locale& loc) { iostreams::imbue(t_, loc); }
117
118 std::streamsize optimal_buffer_size() const
119 { return iostreams::optimal_buffer_size(t_); }
120public:
121 concept_adapter& operator=(const concept_adapter&);
122 value_type t_;
123};
124
125//------------------Specializations of device_wrapper_impl--------------------//
126
127template<>
128struct device_wrapper_impl<any_tag> {
129 template<typename Device, typename Dummy>
130 static std::streampos
131 seek( Device& dev, Dummy*, stream_offset off,
132 NDNBOOST_IOS::seekdir way, NDNBOOST_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
140 seek( Device&, stream_offset, NDNBOOST_IOS::seekdir,
141 NDNBOOST_IOS::openmode, any_tag )
142 {
143 ndnboost::throw_exception(cant_seek());
144 NDNBOOST_IOSTREAMS_UNREACHABLE_RETURN(0)
145 }
146
147 template<typename Device>
148 static std::streampos
149 seek( Device& dev, stream_offset off,
150 NDNBOOST_IOS::seekdir way, NDNBOOST_IOS::openmode which,
151 random_access )
152 {
153 return iostreams::seek(dev, off, way, which);
154 }
155
156 template<typename Device, typename Dummy>
157 static void close(Device& dev, Dummy*, NDNBOOST_IOS::openmode which)
158 { iostreams::close(dev, which); }
159
160 template<typename Device, typename Dummy>
161 static bool flush(Device& dev, Dummy*)
162 { return iostreams::flush(dev); }
163};
164
165
166template<>
167struct device_wrapper_impl<input> : device_wrapper_impl<any_tag> {
168 template<typename Device, typename Dummy>
169 static std::streamsize
170 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
176 write( Device&, Dummy*, const typename char_type_of<Device>::type*,
177 std::streamsize )
178 { ndnboost::throw_exception(cant_write());
179 NDNBOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
180};
181
182template<>
183struct device_wrapper_impl<output> {
184 template<typename Device, typename Dummy>
185 static std::streamsize
186 read(Device&, Dummy*, typename char_type_of<Device>::type*, std::streamsize)
187 { ndnboost::throw_exception(cant_read());
188 NDNBOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
189
190 template<typename Device, typename Dummy>
191 static std::streamsize
192 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
199template<>
200struct flt_wrapper_impl<any_tag> {
201 template<typename Filter, typename Device>
202 static std::streampos
203 seek( Filter& f, Device* dev, stream_offset off,
204 NDNBOOST_IOS::seekdir way, NDNBOOST_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
212 seek( Filter&, Device*, stream_offset,
213 NDNBOOST_IOS::seekdir, NDNBOOST_IOS::openmode, any_tag )
214 { ndnboost::throw_exception(cant_seek());
215 NDNBOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
216
217 template<typename Filter, typename Device>
218 static std::streampos
219 seek( Filter& f, Device* dev, stream_offset off,
220 NDNBOOST_IOS::seekdir way, NDNBOOST_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
229 seek( Filter& f, Device* dev, stream_offset off,
230 NDNBOOST_IOS::seekdir way, NDNBOOST_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
236 seek( Filter& f, Device* dev, stream_offset off,
237 NDNBOOST_IOS::seekdir way, NDNBOOST_IOS::openmode which,
238 random_access, two_sequence )
239 { return f.seek(*dev, off, way, which); }
240
241 template<typename Filter, typename Device>
242 static void close(Filter& f, Device* dev, NDNBOOST_IOS::openmode which)
243 { iostreams::close(f, *dev, which); }
244
245 template<typename Filter, typename Device>
246 static bool flush(Filter& f, Device* dev)
247 { return iostreams::flush(f, *dev); }
248};
249
250template<>
251struct flt_wrapper_impl<input> {
252 template<typename Filter, typename Source>
253 static std::streamsize
254 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
260 write( Filter&, Sink*, const typename char_type_of<Filter>::type*,
261 std::streamsize )
262 { ndnboost::throw_exception(cant_write());
263 NDNBOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
264};
265
266template<>
267struct flt_wrapper_impl<output> {
268 template<typename Filter, typename Source>
269 static std::streamsize
270 read(Filter&, Source*, typename char_type_of<Filter>::type*,std::streamsize)
271 { ndnboost::throw_exception(cant_read());
272 NDNBOOST_IOSTREAMS_UNREACHABLE_RETURN(0) }
273
274 template<typename Filter, typename Sink>
275 static std::streamsize
276 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 <ndnboost/iostreams/detail/config/enable_warnings.hpp> // MSVC.
286
287#endif // #ifndef NDNBOOST_IOSTREAMS_DETAIL_CONCEPT_ADAPTER_HPP_INCLUDED