1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2005-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 namespace boost { namespace iostreams {
9
10 namespace detail {
11
12 template<typename T>
13 struct close_impl;
14
15 } // End namespace detail.
16
17 template<typename T>
close(T & t)18 void close(T& t) { detail::close_all(t); }
19
20 template<typename T>
close(T & t,BOOST_IOS::openmode which)21 void close(T& t, BOOST_IOS::openmode which)
22 {
23 typedef typename detail::unwrapped_type<T>::type unwrapped;
24 detail::close_impl<T>::inner<unwrapped>::close(detail::unwrap(t), which);
25 }
26
27 template<typename T, typename Sink>
close(T & t,Sink & snk,BOOST_IOS::openmode which)28 void close(T& t, Sink& snk, BOOST_IOS::openmode which)
29 {
30 typedef typename detail::unwrapped_type<T>::type unwrapped;
31 detail::close_impl<T>::inner<unwrapped>::close(detail::unwrap(t), snk, which);
32 }
33
34 namespace detail {
35
36 //------------------Definition of close_impl----------------------------------//
37
38 template<typename T>
39 struct close_tag {
40 typedef typename category_of<T>::type category;
41 typedef typename
42 mpl::eval_if<
43 is_convertible<category, closable_tag>,
44 mpl::if_<
45 mpl::or_<
46 is_convertible<category, two_sequence>,
47 is_convertible<category, dual_use>
48 >,
49 two_sequence,
50 closable_tag
51 >,
52 mpl::identity<any_tag>
53 >::type type;
54 };
55
56 template<typename T>
57 struct close_impl
58 : mpl::if_<
59 is_custom<T>,
60 operations<T>,
61 close_impl<BOOST_DEDUCED_TYPENAME close_tag<T>::type>
62 >::type
63 { };
64
65 template<>
66 struct close_impl<any_tag> {
67 template<typename T>
68 struct inner {
closeboost::iostreams::detail::close_impl::inner69 static void close(T& t, BOOST_IOS::openmode which)
70 {
71 if (which == BOOST_IOS::out)
72 iostreams::flush(t);
73 }
74
75 template<typename Sink>
closeboost::iostreams::detail::close_impl::inner76 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
77 {
78 if (which == BOOST_IOS::out) {
79 non_blocking_adapter<Sink> nb(snk);
80 iostreams::flush(t, nb);
81 }
82 }
83 };
84 };
85
86 template<>
87 struct close_impl<closable_tag> {
88 template<typename T>
89 struct inner {
closeboost::iostreams::detail::close_impl::inner90 static void close(T& t, BOOST_IOS::openmode which)
91 {
92 typedef typename category_of<T>::type category;
93 const bool in = is_convertible<category, input>::value &&
94 !is_convertible<category, output>::value;
95 if (in == (which == BOOST_IOS::in))
96 t.close();
97 }
98 template<typename Sink>
closeboost::iostreams::detail::close_impl::inner99 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
100 {
101 typedef typename category_of<T>::type category;
102 const bool in = is_convertible<category, input>::value &&
103 !is_convertible<category, output>::value;
104 if (in == (which == BOOST_IOS::in)) {
105 non_blocking_adapter<Sink> nb(snk);
106 t.close(nb);
107 }
108 }
109 };
110 };
111
112 template<>
113 struct close_impl<two_sequence> {
114 template<typename T>
115 struct inner {
closeboost::iostreams::detail::close_impl::inner116 static void close(T& t, BOOST_IOS::openmode which) { t.close(which); }
117
118 template<typename Sink>
closeboost::iostreams::detail::close_impl::inner119 static void close(T& t, Sink& snk, BOOST_IOS::openmode which)
120 {
121 non_blocking_adapter<Sink> nb(snk);
122 t.close(nb, which);
123 }
124 };
125 };
126
127 } // End namespace detail.
128
129 } } // End namespaces iostreams, boost.
130