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_CLOSE_HPP_INCLUDED |
9 | #define BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED |
10 | |
11 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
12 | # pragma once |
13 | #endif |
14 | |
15 | #include <boost/config.hpp> // DEDUCED_TYPENAME, MSVC. |
16 | #include <boost/detail/workaround.hpp> |
17 | #include <boost/iostreams/categories.hpp> |
18 | #include <boost/iostreams/flush.hpp> |
19 | #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp> |
20 | #include <boost/iostreams/detail/ios.hpp> // BOOST_IOS |
21 | #include <boost/iostreams/detail/select.hpp> |
22 | #include <boost/iostreams/detail/wrap_unwrap.hpp> |
23 | #include <boost/iostreams/operations_fwd.hpp> |
24 | #include <boost/iostreams/traits.hpp> |
25 | #include <boost/mpl/identity.hpp> |
26 | #include <boost/mpl/if.hpp> |
27 | #include <boost/type_traits/is_convertible.hpp> |
28 | #include <boost/type_traits/is_integral.hpp> |
29 | #include <boost/type_traits/remove_cv.hpp> |
30 | #include <boost/type_traits/remove_reference.hpp> |
31 | |
32 | // Must come last. |
33 | #include <boost/iostreams/detail/config/disable_warnings.hpp> |
34 | |
35 | namespace boost { namespace iostreams { |
36 | |
37 | template<typename T> |
38 | void close(T& t); |
39 | |
40 | template<typename T> |
41 | void close(T& t, BOOST_IOS::openmode which); |
42 | |
43 | template<typename T, typename Sink> |
44 | void close(T& t, Sink& snk, BOOST_IOS::openmode which); |
45 | |
46 | namespace detail { |
47 | |
48 | template<typename T> |
49 | void close_all(T& t) |
50 | { |
51 | try { |
52 | boost::iostreams::close(t, BOOST_IOS::in); |
53 | } catch (...) { |
54 | try { |
55 | boost::iostreams::close(t, BOOST_IOS::out); |
56 | } catch (...) { } |
57 | throw; |
58 | } |
59 | boost::iostreams::close(t, BOOST_IOS::out); |
60 | } |
61 | |
62 | template<typename T, typename Sink> |
63 | void close_all(T& t, Sink& snk) |
64 | { |
65 | try { |
66 | boost::iostreams::close(t, snk, BOOST_IOS::in); |
67 | } catch (...) { |
68 | try { |
69 | boost::iostreams::close(t, snk, BOOST_IOS::out); |
70 | } catch (...) { } |
71 | throw; |
72 | } |
73 | boost::iostreams::close(t, snk, BOOST_IOS::out); |
74 | } |
75 | |
76 | } // End namespace detail. |
77 | |
78 | } } // End namespaces iostreams, boost. |
79 | |
80 | #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-----------------------------------// |
81 | # include <boost/iostreams/detail/vc6/close.hpp> |
82 | #else // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //--------------------------// |
83 | |
84 | namespace boost { namespace iostreams { |
85 | |
86 | namespace detail { |
87 | |
88 | template<typename T> |
89 | struct close_impl; |
90 | |
91 | } // End namespace detail. |
92 | |
93 | template<typename T> |
94 | void close(T& t) { detail::close_all(t); } |
95 | |
96 | template<typename T> |
97 | void close(T& t, BOOST_IOS::openmode which) |
98 | { |
99 | #ifdef BOOST_IOSTREAMS_STRICT |
100 | BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out); |
101 | #else |
102 | if (which == (BOOST_IOS::in | BOOST_IOS::out)) { |
103 | detail::close_all(t); |
104 | return; |
105 | } |
106 | #endif |
107 | detail::close_impl<T>::close(detail::unwrap(t), which); |
108 | } |
109 | |
110 | template<typename T, typename Sink> |
111 | void close(T& t, Sink& snk, BOOST_IOS::openmode which) |
112 | { |
113 | #ifdef BOOST_IOSTREAMS_STRICT |
114 | BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out); |
115 | #else |
116 | if (which == (BOOST_IOS::in | BOOST_IOS::out)) { |
117 | detail::close_all(t, snk); |
118 | return; |
119 | } |
120 | #endif |
121 | detail::close_impl<T>::close(detail::unwrap(t), snk, which); |
122 | } |
123 | |
124 | namespace detail { |
125 | |
126 | //------------------Definition of close_impl----------------------------------// |
127 | |
128 | struct close_boost_stream { }; |
129 | struct close_filtering_stream { }; |
130 | |
131 | template<typename T> |
132 | struct close_tag { |
133 | typedef typename category_of<T>::type category; |
134 | typedef typename detail::unwrapped_type<T>::type unwrapped; |
135 | typedef typename |
136 | iostreams::select< |
137 | mpl::not_< is_convertible<category, closable_tag> >, |
138 | any_tag, |
139 | mpl::or_< |
140 | is_boost_stream<unwrapped>, |
141 | is_boost_stream_buffer<unwrapped> |
142 | >, |
143 | close_boost_stream, |
144 | mpl::or_< |
145 | is_filtering_stream<unwrapped>, |
146 | is_filtering_streambuf<unwrapped> |
147 | >, |
148 | close_filtering_stream, |
149 | mpl::or_< |
150 | is_convertible<category, two_sequence>, |
151 | is_convertible<category, dual_use> |
152 | >, |
153 | two_sequence, |
154 | else_, |
155 | closable_tag |
156 | >::type type; |
157 | }; |
158 | |
159 | template<typename T> |
160 | struct close_impl |
161 | : mpl::if_< |
162 | is_custom<T>, |
163 | operations<T>, |
164 | close_impl<BOOST_DEDUCED_TYPENAME close_tag<T>::type> |
165 | >::type |
166 | { }; |
167 | |
168 | template<> |
169 | struct close_impl<any_tag> { |
170 | template<typename T> |
171 | static void close(T& t, BOOST_IOS::openmode which) |
172 | { |
173 | if (which == BOOST_IOS::out) |
174 | iostreams::flush(t); |
175 | } |
176 | |
177 | template<typename T, typename Sink> |
178 | static void close(T& t, Sink& snk, BOOST_IOS::openmode which) |
179 | { |
180 | if (which == BOOST_IOS::out) { |
181 | non_blocking_adapter<Sink> nb(snk); |
182 | iostreams::flush(t, nb); |
183 | } |
184 | } |
185 | }; |
186 | |
187 | template<> |
188 | struct close_impl<close_boost_stream> { |
189 | template<typename T> |
190 | static void close(T& t) |
191 | { |
192 | t.close(); |
193 | } |
194 | template<typename T> |
195 | static void close(T& t, BOOST_IOS::openmode which) |
196 | { |
197 | if (which == BOOST_IOS::out) |
198 | t.close(); |
199 | } |
200 | }; |
201 | |
202 | template<> |
203 | struct close_impl<close_filtering_stream> { |
204 | template<typename T> |
205 | static void close(T& t, BOOST_IOS::openmode which) |
206 | { |
207 | typedef typename category_of<T>::type category; |
208 | const bool in = is_convertible<category, input>::value && |
209 | !is_convertible<category, output>::value; |
210 | if (in == (which == BOOST_IOS::in) && t.is_complete()) |
211 | t.pop(); |
212 | } |
213 | }; |
214 | |
215 | template<> |
216 | struct close_impl<closable_tag> { |
217 | template<typename T> |
218 | static void close(T& t, BOOST_IOS::openmode which) |
219 | { |
220 | typedef typename category_of<T>::type category; |
221 | const bool in = is_convertible<category, input>::value && |
222 | !is_convertible<category, output>::value; |
223 | if (in == (which == BOOST_IOS::in)) |
224 | t.close(); |
225 | } |
226 | template<typename T, typename Sink> |
227 | static void close(T& t, Sink& snk, BOOST_IOS::openmode which) |
228 | { |
229 | typedef typename category_of<T>::type category; |
230 | const bool in = is_convertible<category, input>::value && |
231 | !is_convertible<category, output>::value; |
232 | if (in == (which == BOOST_IOS::in)) { |
233 | non_blocking_adapter<Sink> nb(snk); |
234 | t.close(nb); |
235 | } |
236 | } |
237 | }; |
238 | |
239 | template<> |
240 | struct close_impl<two_sequence> { |
241 | template<typename T> |
242 | static void close(T& t, BOOST_IOS::openmode which) { t.close(which); } |
243 | template<typename T, typename Sink> |
244 | static void close(T& t, Sink& snk, BOOST_IOS::openmode which) |
245 | { |
246 | non_blocking_adapter<Sink> nb(snk); |
247 | t.close(nb, which); |
248 | } |
249 | }; |
250 | |
251 | } // End namespace detail. |
252 | |
253 | } } // End namespaces iostreams, boost. |
254 | |
255 | #endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-------------------------// |
256 | |
257 | #include <boost/iostreams/detail/config/enable_warnings.hpp> |
258 | |
259 | #endif // #ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED |
260 | |