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
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>
33 #include <boost/iostreams/detail/config/disable_warnings.hpp>
35 namespace boost { namespace iostreams {
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);
52 boost::iostreams::close(t, BOOST_IOS::in);
55 boost::iostreams::close(t, BOOST_IOS::out);
59 boost::iostreams::close(t, BOOST_IOS::out);
62 template<typename T, typename Sink>
63 void close_all(T& t, Sink& snk)
66 boost::iostreams::close(t, snk, BOOST_IOS::in);
69 boost::iostreams::close(t, snk, BOOST_IOS::out);
73 boost::iostreams::close(t, snk, BOOST_IOS::out);
76 } // End namespace detail.
78 } } // End namespaces iostreams, boost.
80 namespace boost { namespace iostreams {
87 } // End namespace detail.
90 void close(T& t) { detail::close_all(t); }
93 void close(T& t, BOOST_IOS::openmode which)
95 #ifdef BOOST_IOSTREAMS_STRICT
96 BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out);
98 if (which == (BOOST_IOS::in | BOOST_IOS::out)) {
103 detail::close_impl<T>::close(detail::unwrap(t), which);
106 template<typename T, typename Sink>
107 void close(T& t, Sink& snk, BOOST_IOS::openmode which)
109 #ifdef BOOST_IOSTREAMS_STRICT
110 BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out);
112 if (which == (BOOST_IOS::in | BOOST_IOS::out)) {
113 detail::close_all(t, snk);
117 detail::close_impl<T>::close(detail::unwrap(t), snk, which);
122 //------------------Definition of close_impl----------------------------------//
124 struct close_boost_stream { };
125 struct close_filtering_stream { };
129 typedef typename category_of<T>::type category;
130 typedef typename detail::unwrapped_type<T>::type unwrapped;
133 mpl::not_< is_convertible<category, closable_tag> >,
136 is_boost_stream<unwrapped>,
137 is_boost_stream_buffer<unwrapped>
141 is_filtering_stream<unwrapped>,
142 is_filtering_streambuf<unwrapped>
144 close_filtering_stream,
146 is_convertible<category, two_sequence>,
147 is_convertible<category, dual_use>
160 close_impl<BOOST_DEDUCED_TYPENAME close_tag<T>::type>
165 struct close_impl<any_tag> {
167 static void close(T& t, BOOST_IOS::openmode which)
169 if (which == BOOST_IOS::out)
173 template<typename T, typename Sink>
174 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
176 if (which == BOOST_IOS::out) {
177 non_blocking_adapter<Sink> nb(snk);
178 iostreams::flush(t, nb);
184 struct close_impl<close_boost_stream> {
186 static void close(T& t)
191 static void close(T& t, BOOST_IOS::openmode which)
193 if (which == BOOST_IOS::out)
199 struct close_impl<close_filtering_stream> {
201 static void close(T& t, BOOST_IOS::openmode which)
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())
212 struct close_impl<closable_tag> {
214 static void close(T& t, BOOST_IOS::openmode which)
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))
222 template<typename T, typename Sink>
223 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
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);
236 struct close_impl<two_sequence> {
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)
242 non_blocking_adapter<Sink> nb(snk);
247 } // End namespace detail.
249 } } // End namespaces iostreams, boost.
251 #include <boost/iostreams/detail/config/enable_warnings.hpp>
253 #endif // #ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED