]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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) | |
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 | namespace boost { namespace iostreams { | |
81 | ||
82 | namespace detail { | |
83 | ||
84 | template<typename T> | |
85 | struct close_impl; | |
86 | ||
87 | } // End namespace detail. | |
88 | ||
89 | template<typename T> | |
90 | void close(T& t) { detail::close_all(t); } | |
91 | ||
92 | template<typename T> | |
93 | void close(T& t, BOOST_IOS::openmode which) | |
94 | { | |
95 | #ifdef BOOST_IOSTREAMS_STRICT | |
96 | BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out); | |
97 | #else | |
98 | if (which == (BOOST_IOS::in | BOOST_IOS::out)) { | |
99 | detail::close_all(t); | |
100 | return; | |
101 | } | |
102 | #endif | |
103 | detail::close_impl<T>::close(detail::unwrap(t), which); | |
104 | } | |
105 | ||
106 | template<typename T, typename Sink> | |
107 | void close(T& t, Sink& snk, BOOST_IOS::openmode which) | |
108 | { | |
109 | #ifdef BOOST_IOSTREAMS_STRICT | |
110 | BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out); | |
111 | #else | |
112 | if (which == (BOOST_IOS::in | BOOST_IOS::out)) { | |
113 | detail::close_all(t, snk); | |
114 | return; | |
115 | } | |
116 | #endif | |
117 | detail::close_impl<T>::close(detail::unwrap(t), snk, which); | |
118 | } | |
119 | ||
120 | namespace detail { | |
121 | ||
122 | //------------------Definition of close_impl----------------------------------// | |
123 | ||
124 | struct close_boost_stream { }; | |
125 | struct close_filtering_stream { }; | |
126 | ||
127 | template<typename T> | |
128 | struct close_tag { | |
129 | typedef typename category_of<T>::type category; | |
130 | typedef typename detail::unwrapped_type<T>::type unwrapped; | |
131 | typedef typename | |
132 | iostreams::select< | |
133 | mpl::not_< is_convertible<category, closable_tag> >, | |
134 | any_tag, | |
135 | mpl::or_< | |
136 | is_boost_stream<unwrapped>, | |
137 | is_boost_stream_buffer<unwrapped> | |
138 | >, | |
139 | close_boost_stream, | |
140 | mpl::or_< | |
141 | is_filtering_stream<unwrapped>, | |
142 | is_filtering_streambuf<unwrapped> | |
143 | >, | |
144 | close_filtering_stream, | |
145 | mpl::or_< | |
146 | is_convertible<category, two_sequence>, | |
147 | is_convertible<category, dual_use> | |
148 | >, | |
149 | two_sequence, | |
150 | else_, | |
151 | closable_tag | |
152 | >::type type; | |
153 | }; | |
154 | ||
155 | template<typename T> | |
156 | struct close_impl | |
157 | : mpl::if_< | |
158 | is_custom<T>, | |
159 | operations<T>, | |
160 | close_impl<BOOST_DEDUCED_TYPENAME close_tag<T>::type> | |
161 | >::type | |
162 | { }; | |
163 | ||
164 | template<> | |
165 | struct close_impl<any_tag> { | |
166 | template<typename T> | |
167 | static void close(T& t, BOOST_IOS::openmode which) | |
168 | { | |
169 | if (which == BOOST_IOS::out) | |
170 | iostreams::flush(t); | |
171 | } | |
172 | ||
173 | template<typename T, typename Sink> | |
174 | static void close(T& t, Sink& snk, BOOST_IOS::openmode which) | |
175 | { | |
176 | if (which == BOOST_IOS::out) { | |
177 | non_blocking_adapter<Sink> nb(snk); | |
178 | iostreams::flush(t, nb); | |
179 | } | |
180 | } | |
181 | }; | |
182 | ||
183 | template<> | |
184 | struct close_impl<close_boost_stream> { | |
185 | template<typename T> | |
186 | static void close(T& t) | |
187 | { | |
188 | t.close(); | |
189 | } | |
190 | template<typename T> | |
191 | static void close(T& t, BOOST_IOS::openmode which) | |
192 | { | |
193 | if (which == BOOST_IOS::out) | |
194 | t.close(); | |
195 | } | |
196 | }; | |
197 | ||
198 | template<> | |
199 | struct close_impl<close_filtering_stream> { | |
200 | template<typename T> | |
201 | static void close(T& t, BOOST_IOS::openmode which) | |
202 | { | |
203 | typedef typename category_of<T>::type category; | |
204 | const bool in = is_convertible<category, input>::value && | |
205 | !is_convertible<category, output>::value; | |
206 | if (in == (which == BOOST_IOS::in) && t.is_complete()) | |
207 | t.pop(); | |
208 | } | |
209 | }; | |
210 | ||
211 | template<> | |
212 | struct close_impl<closable_tag> { | |
213 | template<typename T> | |
214 | static void close(T& t, BOOST_IOS::openmode which) | |
215 | { | |
216 | typedef typename category_of<T>::type category; | |
217 | const bool in = is_convertible<category, input>::value && | |
218 | !is_convertible<category, output>::value; | |
219 | if (in == (which == BOOST_IOS::in)) | |
220 | t.close(); | |
221 | } | |
222 | template<typename T, typename Sink> | |
223 | static void close(T& t, Sink& snk, BOOST_IOS::openmode which) | |
224 | { | |
225 | typedef typename category_of<T>::type category; | |
226 | const bool in = is_convertible<category, input>::value && | |
227 | !is_convertible<category, output>::value; | |
228 | if (in == (which == BOOST_IOS::in)) { | |
229 | non_blocking_adapter<Sink> nb(snk); | |
230 | t.close(nb); | |
231 | } | |
232 | } | |
233 | }; | |
234 | ||
235 | template<> | |
236 | struct close_impl<two_sequence> { | |
237 | template<typename T> | |
238 | static void close(T& t, BOOST_IOS::openmode which) { t.close(which); } | |
239 | template<typename T, typename Sink> | |
240 | static void close(T& t, Sink& snk, BOOST_IOS::openmode which) | |
241 | { | |
242 | non_blocking_adapter<Sink> nb(snk); | |
243 | t.close(nb, which); | |
244 | } | |
245 | }; | |
246 | ||
247 | } // End namespace detail. | |
248 | ||
249 | } } // End namespaces iostreams, boost. | |
250 | ||
251 | #include <boost/iostreams/detail/config/enable_warnings.hpp> | |
252 | ||
253 | #endif // #ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED |