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