File indexing completed on 2025-01-18 09:38:53
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED
0009 #define BOOST_IOSTREAMS_CLOSE_HPP_INCLUDED
0010
0011 #if defined(_MSC_VER)
0012 # pragma once
0013 #endif
0014
0015 #include <boost/config.hpp> // DEDUCED_TYPENAME, MSVC.
0016 #include <boost/detail/workaround.hpp>
0017 #include <boost/iostreams/categories.hpp>
0018 #include <boost/iostreams/flush.hpp>
0019 #include <boost/iostreams/detail/adapter/non_blocking_adapter.hpp>
0020 #include <boost/iostreams/detail/ios.hpp> // BOOST_IOS
0021 #include <boost/iostreams/detail/select.hpp>
0022 #include <boost/iostreams/detail/wrap_unwrap.hpp>
0023 #include <boost/iostreams/operations_fwd.hpp>
0024 #include <boost/iostreams/traits.hpp>
0025 #include <boost/mpl/identity.hpp>
0026 #include <boost/mpl/if.hpp>
0027 #include <boost/type_traits/is_convertible.hpp>
0028 #include <boost/type_traits/is_integral.hpp>
0029 #include <boost/type_traits/remove_cv.hpp>
0030 #include <boost/type_traits/remove_reference.hpp>
0031
0032
0033 #include <boost/iostreams/detail/config/disable_warnings.hpp>
0034
0035 namespace boost { namespace iostreams {
0036
0037 template<typename T>
0038 void close(T& t);
0039
0040 template<typename T>
0041 void close(T& t, BOOST_IOS::openmode which);
0042
0043 template<typename T, typename Sink>
0044 void close(T& t, Sink& snk, BOOST_IOS::openmode which);
0045
0046 namespace detail {
0047
0048 template<typename T>
0049 void close_all(T& t)
0050 {
0051 try {
0052 boost::iostreams::close(t, BOOST_IOS::in);
0053 } catch (...) {
0054 try {
0055 boost::iostreams::close(t, BOOST_IOS::out);
0056 } catch (...) { }
0057 throw;
0058 }
0059 boost::iostreams::close(t, BOOST_IOS::out);
0060 }
0061
0062 template<typename T, typename Sink>
0063 void close_all(T& t, Sink& snk)
0064 {
0065 try {
0066 boost::iostreams::close(t, snk, BOOST_IOS::in);
0067 } catch (...) {
0068 try {
0069 boost::iostreams::close(t, snk, BOOST_IOS::out);
0070 } catch (...) { }
0071 throw;
0072 }
0073 boost::iostreams::close(t, snk, BOOST_IOS::out);
0074 }
0075
0076 }
0077
0078 } }
0079
0080 namespace boost { namespace iostreams {
0081
0082 namespace detail {
0083
0084 template<typename T>
0085 struct close_impl;
0086
0087 }
0088
0089 template<typename T>
0090 void close(T& t) { detail::close_all(t); }
0091
0092 template<typename T>
0093 void close(T& t, BOOST_IOS::openmode which)
0094 {
0095 #ifdef BOOST_IOSTREAMS_STRICT
0096 BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out);
0097 #else
0098 if (which == (BOOST_IOS::in | BOOST_IOS::out)) {
0099 detail::close_all(t);
0100 return;
0101 }
0102 #endif
0103 detail::close_impl<T>::close(detail::unwrap(t), which);
0104 }
0105
0106 template<typename T, typename Sink>
0107 void close(T& t, Sink& snk, BOOST_IOS::openmode which)
0108 {
0109 #ifdef BOOST_IOSTREAMS_STRICT
0110 BOOST_ASSERT(which == BOOST_IOS::in || which == BOOST_IOS::out);
0111 #else
0112 if (which == (BOOST_IOS::in | BOOST_IOS::out)) {
0113 detail::close_all(t, snk);
0114 return;
0115 }
0116 #endif
0117 detail::close_impl<T>::close(detail::unwrap(t), snk, which);
0118 }
0119
0120 namespace detail {
0121
0122
0123
0124 struct close_boost_stream { };
0125 struct close_filtering_stream { };
0126
0127 template<typename T>
0128 struct close_tag {
0129 typedef typename category_of<T>::type category;
0130 typedef typename detail::unwrapped_type<T>::type unwrapped;
0131 typedef typename
0132 iostreams::select<
0133 mpl::not_< is_convertible<category, closable_tag> >,
0134 any_tag,
0135 mpl::or_<
0136 is_boost_stream<unwrapped>,
0137 is_boost_stream_buffer<unwrapped>
0138 >,
0139 close_boost_stream,
0140 mpl::or_<
0141 is_filtering_stream<unwrapped>,
0142 is_filtering_streambuf<unwrapped>
0143 >,
0144 close_filtering_stream,
0145 mpl::or_<
0146 is_convertible<category, two_sequence>,
0147 is_convertible<category, dual_use>
0148 >,
0149 two_sequence,
0150 else_,
0151 closable_tag
0152 >::type type;
0153 };
0154
0155 template<typename T>
0156 struct close_impl
0157 : mpl::if_<
0158 is_custom<T>,
0159 operations<T>,
0160 close_impl<BOOST_DEDUCED_TYPENAME close_tag<T>::type>
0161 >::type
0162 { };
0163
0164 template<>
0165 struct close_impl<any_tag> {
0166 template<typename T>
0167 static void close(T& t, BOOST_IOS::openmode which)
0168 {
0169 if (which == BOOST_IOS::out)
0170 iostreams::flush(t);
0171 }
0172
0173 template<typename T, typename Sink>
0174 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
0175 {
0176 if (which == BOOST_IOS::out) {
0177 non_blocking_adapter<Sink> nb(snk);
0178 iostreams::flush(t, nb);
0179 }
0180 }
0181 };
0182
0183 template<>
0184 struct close_impl<close_boost_stream> {
0185 template<typename T>
0186 static void close(T& t)
0187 {
0188 t.close();
0189 }
0190 template<typename T>
0191 static void close(T& t, BOOST_IOS::openmode which)
0192 {
0193 if (which == BOOST_IOS::out)
0194 t.close();
0195 }
0196 };
0197
0198 template<>
0199 struct close_impl<close_filtering_stream> {
0200 template<typename T>
0201 static void close(T& t, BOOST_IOS::openmode which)
0202 {
0203 typedef typename category_of<T>::type category;
0204 const bool in = is_convertible<category, input>::value &&
0205 !is_convertible<category, output>::value;
0206 if (in == (which == BOOST_IOS::in) && t.is_complete())
0207 t.pop();
0208 }
0209 };
0210
0211 template<>
0212 struct close_impl<closable_tag> {
0213 template<typename T>
0214 static void close(T& t, BOOST_IOS::openmode which)
0215 {
0216 typedef typename category_of<T>::type category;
0217 const bool in = is_convertible<category, input>::value &&
0218 !is_convertible<category, output>::value;
0219 if (in == (which == BOOST_IOS::in))
0220 t.close();
0221 }
0222 template<typename T, typename Sink>
0223 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
0224 {
0225 typedef typename category_of<T>::type category;
0226 const bool in = is_convertible<category, input>::value &&
0227 !is_convertible<category, output>::value;
0228 if (in == (which == BOOST_IOS::in)) {
0229 non_blocking_adapter<Sink> nb(snk);
0230 t.close(nb);
0231 }
0232 }
0233 };
0234
0235 template<>
0236 struct close_impl<two_sequence> {
0237 template<typename T>
0238 static void close(T& t, BOOST_IOS::openmode which) { t.close(which); }
0239 template<typename T, typename Sink>
0240 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
0241 {
0242 non_blocking_adapter<Sink> nb(snk);
0243 t.close(nb, which);
0244 }
0245 };
0246
0247 }
0248
0249 } }
0250
0251 #include <boost/iostreams/detail/config/enable_warnings.hpp>
0252
0253 #endif