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