fix doc example typo
[boost.git] / boost / iostreams / close.hpp
blobb17d75111646f1fb166e4904c1a64679efedaa9a
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.)
6 // See http://www.boost.org/libs/iostreams for documentation.
8 #ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED
11 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
12 # pragma once
13 #endif
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>
32 // Must come last.
33 #include <boost/iostreams/detail/config/disable_warnings.hpp>
35 namespace boost { namespace iostreams {
37 template<typename T>
38 void close(T& t);
40 template<typename T>
41 void close(T& t, BOOST_IOS::openmode which);
43 template<typename T, typename Sink>
44 void close(T& t, Sink& snk, BOOST_IOS::openmode which);
46 namespace detail {
48 template<typename T>
49 void close_all(T& t)
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;
59 boost::iostreams::close(t, BOOST_IOS::out);
62 template<typename T, typename Sink>
63 void close_all(T& t, Sink& snk)
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;
73 boost::iostreams::close(t, snk, BOOST_IOS::out);
76 } // End namespaces detail.
78 } } // End namespaces iostreams, boost.
80 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-----------------------------------//
81 # include <boost/iostreams/detail/vc6/close.hpp>
82 #else // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //--------------------------//
84 namespace boost { namespace iostreams {
86 namespace detail {
88 template<typename T>
89 struct close_impl;
91 } // End namespace detail.
93 template<typename T>
94 void close(T& t) { detail::close_all(t); }
96 template<typename T>
97 void close(T& t, BOOST_IOS::openmode which)
99 #ifdef BOOST_IOSTREAMS_STRICT
100 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;
106 #endif
107 detail::close_impl<T>::close(detail::unwrap(t), which);
110 template<typename T, typename Sink>
111 void close(T& t, Sink& snk, BOOST_IOS::openmode which)
113 #ifdef BOOST_IOSTREAMS_STRICT
114 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;
120 #endif
121 detail::close_impl<T>::close(detail::unwrap(t), snk, which);
124 namespace detail {
126 //------------------Definition of close_impl----------------------------------//
128 struct close_boost_stream { };
129 struct close_filtering_stream { };
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>
143 close_boost_stream,
144 mpl::or_<
145 is_filtering_stream<unwrapped>,
146 is_filtering_streambuf<unwrapped>
148 close_filtering_stream,
149 mpl::or_<
150 is_convertible<category, two_sequence>,
151 is_convertible<category, dual_use>
153 two_sequence,
154 else_,
155 closable_tag
156 >::type type;
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 { };
168 template<>
169 struct close_impl<any_tag> {
170 template<typename T>
171 static void close(T& t, BOOST_IOS::openmode which)
173 if (which == BOOST_IOS::out)
174 iostreams::flush(t);
177 template<typename T, typename Sink>
178 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
180 if (which == BOOST_IOS::out) {
181 non_blocking_adapter<Sink> nb(snk);
182 iostreams::flush(t, nb);
187 template<>
188 struct close_impl<close_boost_stream> {
189 template<typename T>
190 static void close(T& t)
192 t.close();
194 template<typename T>
195 static void close(T& t, BOOST_IOS::openmode which)
197 if (which == BOOST_IOS::out)
198 t.close();
202 template<>
203 struct close_impl<close_filtering_stream> {
204 template<typename T>
205 static void close(T& t, BOOST_IOS::openmode which)
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();
215 #include <boost/iostreams/detail/config/disable_warnings.hpp> // Borland.
216 template<>
217 struct close_impl<closable_tag> {
218 template<typename T>
219 static void close(T& t, BOOST_IOS::openmode which)
221 typedef typename category_of<T>::type category;
222 const bool in = is_convertible<category, input>::value &&
223 !is_convertible<category, output>::value;
224 if (in == (which == BOOST_IOS::in))
225 t.close();
227 template<typename T, typename Sink>
228 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
230 typedef typename category_of<T>::type category;
231 const bool in = is_convertible<category, input>::value &&
232 !is_convertible<category, output>::value;
233 if (in == (which == BOOST_IOS::in)) {
234 non_blocking_adapter<Sink> nb(snk);
235 t.close(nb);
240 template<>
241 struct close_impl<two_sequence> {
242 template<typename T>
243 static void close(T& t, BOOST_IOS::openmode which) { t.close(which); }
244 template<typename T, typename Sink>
245 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
247 non_blocking_adapter<Sink> nb(snk);
248 t.close(nb, which);
252 } // End namespace detail.
254 } } // End namespaces iostreams, boost.
256 #endif // #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) //-------------------------//
258 #include <boost/iostreams/detail/config/enable_warnings.hpp>
260 #endif // #ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED