blob: 8ffcf6379e7db4a6b7f3cef0fb55300ba53c4019 [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// To do: add support for random-access.
9
10#ifndef NDNBOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
11#define NDNBOOST_IOSTREAMS_COMBINE_HPP_INCLUDED
12
13#if defined(_MSC_VER) && (_MSC_VER >= 1020)
14# pragma once
15#endif
16
17#include <ndnboost/config.hpp> // NO_STD_LOCALE, DEDUCED_TYPENAME.
18#ifndef NDNBOOST_NO_STD_LOCALE
19# include <locale>
20#endif
21#include <ndnboost/iostreams/detail/ios.hpp>
22#include <ndnboost/iostreams/detail/wrap_unwrap.hpp>
23#include <ndnboost/iostreams/traits.hpp>
24#include <ndnboost/iostreams/operations.hpp>
25#include <ndnboost/mpl/if.hpp>
26#include <ndnboost/static_assert.hpp>
27#include <ndnboost/type_traits/is_convertible.hpp>
28#include <ndnboost/type_traits/is_same.hpp>
29
30// Must come last.
31#include <ndnboost/iostreams/detail/config/disable_warnings.hpp>
32
33namespace ndnboost { namespace iostreams {
34
35namespace detail {
36
37//
38// Template name: combined_device.
39// Description: Model of Device defined in terms of a Source/Sink pair.
40// Template parameters:
41// Source - A model of Source, with the same char_type and traits_type
42// as Sink.
43// Sink - A model of Sink, with the same char_type and traits_type
44// as Source.
45//
46template<typename Source, typename Sink>
47class combined_device {
48private:
49 typedef typename category_of<Source>::type in_category;
50 typedef typename category_of<Sink>::type out_category;
51 typedef typename char_type_of<Sink>::type sink_char_type;
52public:
53 typedef typename char_type_of<Source>::type char_type;
54 struct category
55 : bidirectional,
56 device_tag,
57 closable_tag,
58 localizable_tag
59 { };
60 NDNBOOST_STATIC_ASSERT(is_device<Source>::value);
61 NDNBOOST_STATIC_ASSERT(is_device<Sink>::value);
62 NDNBOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
63 NDNBOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
64 NDNBOOST_STATIC_ASSERT((is_same<char_type, sink_char_type>::value));
65 combined_device(const Source& src, const Sink& snk);
66 std::streamsize read(char_type* s, std::streamsize n);
67 std::streamsize write(const char_type* s, std::streamsize n);
68 void close(NDNBOOST_IOS::openmode);
69 #ifndef NDNBOOST_NO_STD_LOCALE
70 void imbue(const std::locale& loc);
71 #endif
72private:
73 Source src_;
74 Sink sink_;
75};
76
77//
78// Template name: combined_filter.
79// Description: Model of Device defined in terms of a Source/Sink pair.
80// Template parameters:
81// InputFilter - A model of InputFilter, with the same char_type as
82// OutputFilter.
83// OutputFilter - A model of OutputFilter, with the same char_type as
84// InputFilter.
85//
86template<typename InputFilter, typename OutputFilter>
87class combined_filter {
88private:
89 typedef typename category_of<InputFilter>::type in_category;
90 typedef typename category_of<OutputFilter>::type out_category;
91 typedef typename char_type_of<OutputFilter>::type output_char_type;
92public:
93 typedef typename char_type_of<InputFilter>::type char_type;
94 struct category
95 : multichar_bidirectional_filter_tag,
96 closable_tag,
97 localizable_tag
98 { };
99 NDNBOOST_STATIC_ASSERT(is_filter<InputFilter>::value);
100 NDNBOOST_STATIC_ASSERT(is_filter<OutputFilter>::value);
101 NDNBOOST_STATIC_ASSERT((is_convertible<in_category, input>::value));
102 NDNBOOST_STATIC_ASSERT((is_convertible<out_category, output>::value));
103 NDNBOOST_STATIC_ASSERT((is_same<char_type, output_char_type>::value));
104 combined_filter(const InputFilter& in, const OutputFilter& out);
105
106 template<typename Source>
107 std::streamsize read(Source& src, char_type* s, std::streamsize n)
108 { return ndnboost::iostreams::read(in_, src, s, n); }
109
110 template<typename Sink>
111 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
112 { return ndnboost::iostreams::write(out_, snk, s, n); }
113
114 template<typename Sink>
115 void close(Sink& snk, NDNBOOST_IOS::openmode which)
116 {
117 if (which == NDNBOOST_IOS::in) {
118 if (is_convertible<in_category, dual_use>::value) {
119 iostreams::close(in_, snk, NDNBOOST_IOS::in);
120 } else {
121 detail::close_all(in_, snk);
122 }
123 }
124 if (which == NDNBOOST_IOS::out) {
125 if (is_convertible<out_category, dual_use>::value) {
126 iostreams::close(out_, snk, NDNBOOST_IOS::out);
127 } else {
128 detail::close_all(out_, snk);
129 }
130 }
131 }
132 #ifndef NDNBOOST_NO_STD_LOCALE
133 void imbue(const std::locale& loc);
134 #endif
135private:
136 InputFilter in_;
137 OutputFilter out_;
138};
139
140template<typename In, typename Out>
141struct combination_traits
142 : mpl::if_<
143 is_device<In>,
144 combined_device<
145 typename wrapped_type<In>::type,
146 typename wrapped_type<Out>::type
147 >,
148 combined_filter<
149 typename wrapped_type<In>::type,
150 typename wrapped_type<Out>::type
151 >
152 >
153 { };
154
155} // End namespace detail.
156
157template<typename In, typename Out>
158struct combination : detail::combination_traits<In, Out>::type {
159 typedef typename detail::combination_traits<In, Out>::type base_type;
160 typedef typename detail::wrapped_type<In>::type in_type;
161 typedef typename detail::wrapped_type<Out>::type out_type;
162 combination(const in_type& in, const out_type& out)
163 : base_type(in, out) { }
164};
165
166namespace detail {
167
168// Workaround for VC6 ETI bug.
169template<typename In, typename Out>
170struct combine_traits {
171 typedef combination<
172 NDNBOOST_DEDUCED_TYPENAME detail::unwrapped_type<In>::type,
173 NDNBOOST_DEDUCED_TYPENAME detail::unwrapped_type<Out>::type
174 > type;
175};
176
177} // End namespace detail.
178
179//
180// Template name: combine.
181// Description: Takes a Source/Sink pair or InputFilter/OutputFilter pair and
182// returns a Source or Filter which performs input using the first member
183// of the pair and output using the second member of the pair.
184// Template parameters:
185// In - A model of Source or InputFilter, with the same char_type as Out.
186// Out - A model of Sink or OutputFilter, with the same char_type as In.
187//
188template<typename In, typename Out>
189typename detail::combine_traits<In, Out>::type
190combine(const In& in, const Out& out)
191{
192 typedef typename detail::combine_traits<In, Out>::type return_type;
193 return return_type(in, out);
194}
195
196//----------------------------------------------------------------------------//
197
198namespace detail {
199
200//--------------Implementation of combined_device-----------------------------//
201
202template<typename Source, typename Sink>
203inline combined_device<Source, Sink>::combined_device
204 (const Source& src, const Sink& snk)
205 : src_(src), sink_(snk) { }
206
207template<typename Source, typename Sink>
208inline std::streamsize
209combined_device<Source, Sink>::read(char_type* s, std::streamsize n)
210{ return iostreams::read(src_, s, n); }
211
212template<typename Source, typename Sink>
213inline std::streamsize
214combined_device<Source, Sink>::write(const char_type* s, std::streamsize n)
215{ return iostreams::write(sink_, s, n); }
216
217template<typename Source, typename Sink>
218inline void
219combined_device<Source, Sink>::close(NDNBOOST_IOS::openmode which)
220{
221 if (which == NDNBOOST_IOS::in)
222 detail::close_all(src_);
223 if (which == NDNBOOST_IOS::out)
224 detail::close_all(sink_);
225}
226
227#ifndef NDNBOOST_NO_STD_LOCALE
228 template<typename Source, typename Sink>
229 void combined_device<Source, Sink>::imbue(const std::locale& loc)
230 {
231 iostreams::imbue(src_, loc);
232 iostreams::imbue(sink_, loc);
233 }
234#endif
235
236//--------------Implementation of filter_pair---------------------------------//
237
238template<typename InputFilter, typename OutputFilter>
239inline combined_filter<InputFilter, OutputFilter>::combined_filter
240 (const InputFilter& in, const OutputFilter& out) : in_(in), out_(out)
241 { }
242
243#ifndef NDNBOOST_NO_STD_LOCALE
244 template<typename InputFilter, typename OutputFilter>
245 void combined_filter<InputFilter, OutputFilter>::imbue
246 (const std::locale& loc)
247 {
248 iostreams::imbue(in_, loc);
249 iostreams::imbue(out_, loc);
250 }
251#endif
252
253
254} // End namespace detail.
255
256} } // End namespaces iostreams, boost.
257
258#include <ndnboost/iostreams/detail/config/enable_warnings.hpp>
259
260#endif // #ifndef NDNBOOST_IOSTREAMS_COMBINE_HPP_INCLUDED