]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/iostreams/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / iostreams / include / boost / iostreams / detail / streambuf / direct_streambuf.hpp
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.)
5
6 // See http://www.boost.org/libs/iostreams for documentation.
7
8 #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED
10
11 #if defined(_MSC_VER)
12 # pragma once
13 #endif
14
15 #include <boost/assert.hpp>
16 #include <cstddef>
17 #include <typeinfo>
18 #include <utility> // pair.
19 #include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME,
20 #include <boost/iostreams/detail/char_traits.hpp> // member template friends.
21 #include <boost/iostreams/detail/config/wide_streams.hpp>
22 #include <boost/iostreams/detail/error.hpp>
23 #include <boost/iostreams/detail/execute.hpp>
24 #include <boost/iostreams/detail/functional.hpp>
25 #include <boost/iostreams/detail/ios.hpp>
26 #include <boost/iostreams/detail/optional.hpp>
27 #include <boost/iostreams/detail/streambuf.hpp>
28 #include <boost/iostreams/detail/streambuf/linked_streambuf.hpp>
29 #include <boost/iostreams/operations.hpp>
30 #include <boost/iostreams/positioning.hpp>
31 #include <boost/iostreams/traits.hpp>
32 #include <boost/throw_exception.hpp>
33
34 // Must come last.
35 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
36
37 namespace boost { namespace iostreams {
38
39 namespace detail {
40
41 template< typename T,
42 typename Tr =
43 BOOST_IOSTREAMS_CHAR_TRAITS(
44 BOOST_DEDUCED_TYPENAME char_type_of<T>::type
45 ) >
46 class direct_streambuf
47 : public linked_streambuf<BOOST_DEDUCED_TYPENAME char_type_of<T>::type, Tr>
48 {
49 public:
50 typedef typename char_type_of<T>::type char_type;
51 BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr)
52 private:
53 typedef linked_streambuf<char_type, traits_type> base_type;
54 typedef typename category_of<T>::type category;
55 typedef BOOST_IOSTREAMS_BASIC_STREAMBUF(
56 char_type, traits_type
57 ) streambuf_type;
58 public: // stream needs access.
59 void open(const T& t, std::streamsize buffer_size,
60 std::streamsize pback_size);
61 bool is_open() const;
62 void close();
63 bool auto_close() const { return auto_close_; }
64 void set_auto_close(bool close) { auto_close_ = close; }
65 bool strict_sync() { return true; }
66
67 // Declared in linked_streambuf.
68 T* component() { return storage_.get(); }
69 protected:
70 BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type)
71 direct_streambuf();
72
73 //--------------Virtual functions-----------------------------------------//
74
75 // Declared in linked_streambuf.
76 void close_impl(BOOST_IOS::openmode m);
77 const std::type_info& component_type() const { return typeid(T); }
78 void* component_impl() { return component(); }
79 #ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
80 public:
81 #endif
82
83 // Declared in basic_streambuf.
84 int_type underflow();
85 int_type pbackfail(int_type c);
86 int_type overflow(int_type c);
87 pos_type seekoff( off_type off, BOOST_IOS::seekdir way,
88 BOOST_IOS::openmode which );
89 pos_type seekpos(pos_type sp, BOOST_IOS::openmode which);
90 private:
91 pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way,
92 BOOST_IOS::openmode which );
93 void init_input(any_tag) { }
94 void init_input(input);
95 void init_output(any_tag) { }
96 void init_output(output);
97 void init_get_area();
98 void init_put_area();
99 bool one_head() const;
100 bool two_head() const;
101 optional<T> storage_;
102 char_type *ibeg_, *iend_, *obeg_, *oend_;
103 bool auto_close_;
104 };
105
106 //------------------Implementation of direct_streambuf------------------------//
107
108 template<typename T, typename Tr>
109 direct_streambuf<T, Tr>::direct_streambuf()
110 : ibeg_(0), iend_(0), obeg_(0), oend_(0), auto_close_(true)
111 { this->set_true_eof(true); }
112
113 template<typename T, typename Tr>
114 void direct_streambuf<T, Tr>::open
115 (const T& t, std::streamsize, std::streamsize)
116 {
117 storage_.reset(t);
118 init_input(category());
119 init_output(category());
120 setg(0, 0, 0);
121 setp(0, 0);
122 this->set_needs_close();
123 }
124
125 template<typename T, typename Tr>
126 bool direct_streambuf<T, Tr>::is_open() const
127 { return ibeg_ != 0 || obeg_ != 0; }
128
129 template<typename T, typename Tr>
130 void direct_streambuf<T, Tr>::close()
131 {
132 base_type* self = this;
133 detail::execute_all( detail::call_member_close(*self, BOOST_IOS::in),
134 detail::call_member_close(*self, BOOST_IOS::out),
135 detail::call_reset(storage_) );
136 }
137
138 template<typename T, typename Tr>
139 typename direct_streambuf<T, Tr>::int_type
140 direct_streambuf<T, Tr>::underflow()
141 {
142 if (!ibeg_)
143 boost::throw_exception(cant_read());
144 if (!gptr())
145 init_get_area();
146 return gptr() != iend_ ?
147 traits_type::to_int_type(*gptr()) :
148 traits_type::eof();
149 }
150
151 template<typename T, typename Tr>
152 typename direct_streambuf<T, Tr>::int_type
153 direct_streambuf<T, Tr>::pbackfail(int_type c)
154 {
155 using namespace std;
156 if (!ibeg_)
157 boost::throw_exception(cant_read());
158 if (gptr() != 0 && gptr() != ibeg_) {
159 gbump(-1);
160 if (!traits_type::eq_int_type(c, traits_type::eof()))
161 *gptr() = traits_type::to_char_type(c);
162 return traits_type::not_eof(c);
163 }
164 boost::throw_exception(bad_putback());
165 }
166
167 template<typename T, typename Tr>
168 typename direct_streambuf<T, Tr>::int_type
169 direct_streambuf<T, Tr>::overflow(int_type c)
170 {
171 using namespace std;
172 if (!obeg_)
173 boost::throw_exception(BOOST_IOSTREAMS_FAILURE("no write access"));
174 if (!pptr()) init_put_area();
175 if (!traits_type::eq_int_type(c, traits_type::eof())) {
176 if (pptr() == oend_)
177 boost::throw_exception(
178 BOOST_IOSTREAMS_FAILURE("write area exhausted")
179 );
180 *pptr() = traits_type::to_char_type(c);
181 pbump(1);
182 return c;
183 }
184 return traits_type::not_eof(c);
185 }
186
187 template<typename T, typename Tr>
188 inline typename direct_streambuf<T, Tr>::pos_type
189 direct_streambuf<T, Tr>::seekoff
190 (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
191 { return seek_impl(off, way, which); }
192
193 template<typename T, typename Tr>
194 inline typename direct_streambuf<T, Tr>::pos_type
195 direct_streambuf<T, Tr>::seekpos
196 (pos_type sp, BOOST_IOS::openmode which)
197 {
198 return seek_impl(position_to_offset(sp), BOOST_IOS::beg, which);
199 }
200
201 template<typename T, typename Tr>
202 void direct_streambuf<T, Tr>::close_impl(BOOST_IOS::openmode which)
203 {
204 if (which == BOOST_IOS::in && ibeg_ != 0) {
205 setg(0, 0, 0);
206 ibeg_ = iend_ = 0;
207 }
208 if (which == BOOST_IOS::out && obeg_ != 0) {
209 sync();
210 setp(0, 0);
211 obeg_ = oend_ = 0;
212 }
213 boost::iostreams::close(*storage_, which);
214 }
215
216 template<typename T, typename Tr>
217 typename direct_streambuf<T, Tr>::pos_type direct_streambuf<T, Tr>::seek_impl
218 (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
219 {
220 using namespace std;
221 BOOST_IOS::openmode both = BOOST_IOS::in | BOOST_IOS::out;
222 if (two_head() && (which & both) == both)
223 boost::throw_exception(bad_seek());
224 stream_offset result = -1;
225 bool one = one_head();
226 if (one && (pptr() != 0 || gptr()== 0))
227 init_get_area(); // Switch to input mode, for code reuse.
228 if (one || ((which & BOOST_IOS::in) != 0 && ibeg_ != 0)) {
229 if (!gptr()) setg(ibeg_, ibeg_, iend_);
230 ptrdiff_t next = 0;
231 switch (way) {
232 case BOOST_IOS::beg: next = off; break;
233 case BOOST_IOS::cur: next = (gptr() - ibeg_) + off; break;
234 case BOOST_IOS::end: next = (iend_ - ibeg_) + off; break;
235 default: BOOST_ASSERT(0);
236 }
237 if (next < 0 || next > (iend_ - ibeg_))
238 boost::throw_exception(bad_seek());
239 setg(ibeg_, ibeg_ + next, iend_);
240 result = next;
241 }
242 if (!one && (which & BOOST_IOS::out) != 0 && obeg_ != 0) {
243 if (!pptr()) setp(obeg_, oend_);
244 ptrdiff_t next = 0;
245 switch (way) {
246 case BOOST_IOS::beg: next = off; break;
247 case BOOST_IOS::cur: next = (pptr() - obeg_) + off; break;
248 case BOOST_IOS::end: next = (oend_ - obeg_) + off; break;
249 default: BOOST_ASSERT(0);
250 }
251 if (next < 0 || next > (oend_ - obeg_))
252 boost::throw_exception(bad_seek());
253 pbump(static_cast<int>(next - (pptr() - obeg_)));
254 result = next;
255 }
256 return offset_to_position(result);
257 }
258
259 template<typename T, typename Tr>
260 void direct_streambuf<T, Tr>::init_input(input)
261 {
262 std::pair<char_type*, char_type*> p = input_sequence(*storage_);
263 ibeg_ = p.first;
264 iend_ = p.second;
265 }
266
267 template<typename T, typename Tr>
268 void direct_streambuf<T, Tr>::init_output(output)
269 {
270 std::pair<char_type*, char_type*> p = output_sequence(*storage_);
271 obeg_ = p.first;
272 oend_ = p.second;
273 }
274
275 template<typename T, typename Tr>
276 void direct_streambuf<T, Tr>::init_get_area()
277 {
278 setg(ibeg_, ibeg_, iend_);
279 if (one_head() && pptr()) {
280 gbump(static_cast<int>(pptr() - obeg_));
281 setp(0, 0);
282 }
283 }
284
285 template<typename T, typename Tr>
286 void direct_streambuf<T, Tr>::init_put_area()
287 {
288 setp(obeg_, oend_);
289 if (one_head() && gptr()) {
290 pbump(static_cast<int>(gptr() - ibeg_));
291 setg(0, 0, 0);
292 }
293 }
294
295 template<typename T, typename Tr>
296 inline bool direct_streambuf<T, Tr>::one_head() const
297 { return ibeg_ && obeg_ && ibeg_ == obeg_; }
298
299 template<typename T, typename Tr>
300 inline bool direct_streambuf<T, Tr>::two_head() const
301 { return ibeg_ && obeg_ && ibeg_ != obeg_; }
302
303 //----------------------------------------------------------------------------//
304
305 } // End namespace detail.
306
307 } } // End namespaces iostreams, boost.
308
309 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC
310
311 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED