1 | // (C) Copyright Jonathan Turkanis 2003. |
---|
2 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
---|
3 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) |
---|
4 | |
---|
5 | // See http://www.boost.org/libs/iostreams for documentation. |
---|
6 | |
---|
7 | #ifndef BOOST_IOSTREAMS_DETAIL_CLOSER_HPP_INCLUDED |
---|
8 | #define BOOST_IOSTREAMS_DETAIL_CLOSER_HPP_INCLUDED |
---|
9 | |
---|
10 | #if defined(_MSC_VER) && (_MSC_VER >= 1020) |
---|
11 | # pragma once |
---|
12 | #endif |
---|
13 | |
---|
14 | #include <exception> // exception. |
---|
15 | #include <boost/iostreams/detail/ios.hpp> // openmode. |
---|
16 | #include <boost/iostreams/operations.hpp> // close |
---|
17 | #include <boost/iostreams/traits.hpp> // is_device. |
---|
18 | #include <boost/mpl/if.hpp> |
---|
19 | |
---|
20 | namespace boost { namespace iostreams { namespace detail { |
---|
21 | |
---|
22 | template<typename T> |
---|
23 | struct closer { |
---|
24 | closer(T& t) : t_(&t) { } |
---|
25 | ~closer() { try { t_->close(); } catch (std::exception&) { } } |
---|
26 | T* t_; |
---|
27 | }; |
---|
28 | |
---|
29 | template<typename Device> |
---|
30 | struct external_device_closer { |
---|
31 | external_device_closer(Device& dev, BOOST_IOS::openmode which) |
---|
32 | : device_(&dev), which_(which), |
---|
33 | dummy_(true), nothrow_(dummy_) |
---|
34 | { } |
---|
35 | external_device_closer(Device& dev, BOOST_IOS::openmode which, bool& nothrow) |
---|
36 | : device_(&dev), which_(which), |
---|
37 | dummy_(true), nothrow_(nothrow) |
---|
38 | { } |
---|
39 | ~external_device_closer() |
---|
40 | { |
---|
41 | try { |
---|
42 | boost::iostreams::close(*device_, which_); |
---|
43 | } catch (...) { |
---|
44 | if (!nothrow_) { |
---|
45 | nothrow_ = true; |
---|
46 | throw; |
---|
47 | } |
---|
48 | } |
---|
49 | } |
---|
50 | Device* device_; |
---|
51 | BOOST_IOS::openmode which_; |
---|
52 | bool dummy_; |
---|
53 | bool& nothrow_; |
---|
54 | }; |
---|
55 | |
---|
56 | template<typename Filter, typename Device> |
---|
57 | struct external_filter_closer { |
---|
58 | external_filter_closer(Filter& flt, Device& dev, BOOST_IOS::openmode which) |
---|
59 | : filter_(flt), device_(dev), which_(which), |
---|
60 | dummy_(true), nothrow_(dummy_) |
---|
61 | { } |
---|
62 | external_filter_closer( Filter& flt, Device& dev, |
---|
63 | BOOST_IOS::openmode which, bool& nothrow ) |
---|
64 | : filter_(flt), device_(dev), which_(which), |
---|
65 | dummy_(true), nothrow_(nothrow) |
---|
66 | { } |
---|
67 | ~external_filter_closer() |
---|
68 | { |
---|
69 | try { |
---|
70 | boost::iostreams::close(filter_, device_, which_); |
---|
71 | } catch (...) { |
---|
72 | if (!nothrow_) { |
---|
73 | nothrow_ = true; |
---|
74 | throw; |
---|
75 | } |
---|
76 | } |
---|
77 | } |
---|
78 | Filter& filter_; |
---|
79 | Device& device_; |
---|
80 | BOOST_IOS::openmode which_; |
---|
81 | bool dummy_; |
---|
82 | bool& nothrow_; |
---|
83 | }; |
---|
84 | |
---|
85 | template<typename FilterOrDevice, typename DeviceOrDummy = int> |
---|
86 | struct external_closer_traits { |
---|
87 | typedef typename |
---|
88 | mpl::if_< |
---|
89 | is_device<FilterOrDevice>, |
---|
90 | external_device_closer<FilterOrDevice>, |
---|
91 | external_filter_closer<FilterOrDevice, DeviceOrDummy> |
---|
92 | >::type type; |
---|
93 | }; |
---|
94 | |
---|
95 | template<typename FilterOrDevice, typename DeviceOrDummy = int> |
---|
96 | struct external_closer |
---|
97 | : external_closer_traits<FilterOrDevice, DeviceOrDummy>::type |
---|
98 | { |
---|
99 | typedef typename |
---|
100 | external_closer_traits< |
---|
101 | FilterOrDevice, DeviceOrDummy |
---|
102 | >::type base_type; |
---|
103 | external_closer(FilterOrDevice& dev, BOOST_IOS::openmode which) |
---|
104 | : base_type(dev, which) |
---|
105 | { BOOST_STATIC_ASSERT(is_device<FilterOrDevice>::value); }; |
---|
106 | external_closer( FilterOrDevice& dev, BOOST_IOS::openmode which, |
---|
107 | bool& nothrow ) |
---|
108 | : base_type(dev, which, nothrow) |
---|
109 | { BOOST_STATIC_ASSERT(is_device<FilterOrDevice>::value); }; |
---|
110 | external_closer( FilterOrDevice& flt, DeviceOrDummy& dev, |
---|
111 | BOOST_IOS::openmode which ) |
---|
112 | : base_type(flt, dev, which) |
---|
113 | { BOOST_STATIC_ASSERT(is_filter<FilterOrDevice>::value); }; |
---|
114 | external_closer( FilterOrDevice& flt, DeviceOrDummy& dev, |
---|
115 | BOOST_IOS::openmode which, bool& nothrow ) |
---|
116 | : base_type(flt, dev, which, nothrow) |
---|
117 | { BOOST_STATIC_ASSERT(is_filter<FilterOrDevice>::value); }; |
---|
118 | }; |
---|
119 | |
---|
120 | } } } // End namespaces detail, iostreams, boost. |
---|
121 | |
---|
122 | #endif // #ifndef BOOST_IOSTREAMS_DETAIL_CLOSER_HPP_INCLUDED |
---|