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