Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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 // See http://www.boost.org/libs/iostreams for documentation. | |
6 | |
7 // This material is heavily indebted to the discussion and code samples in | |
8 // A. Langer and K. Kreft, "Standard C++ IOStreams and Locales", | |
9 // Addison-Wesley, 2000, pp. 228-43. | |
10 | |
11 // User "GMSB" provided an optimization for small seeks. | |
12 | |
13 #ifndef BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED | |
14 #define BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED | |
15 | |
16 #include <algorithm> // min, max. | |
17 #include <cassert> | |
18 #include <exception> | |
19 #include <typeinfo> | |
20 #include <boost/config.hpp> // Member template friends. | |
21 #include <boost/detail/workaround.hpp> | |
22 #include <boost/iostreams/constants.hpp> | |
23 #include <boost/iostreams/detail/adapter/concept_adapter.hpp> | |
24 #include <boost/iostreams/detail/buffer.hpp> | |
25 #include <boost/iostreams/detail/config/wide_streams.hpp> | |
26 #include <boost/iostreams/detail/double_object.hpp> | |
27 #include <boost/iostreams/detail/execute.hpp> | |
28 #include <boost/iostreams/detail/functional.hpp> | |
29 #include <boost/iostreams/detail/ios.hpp> | |
30 #include <boost/iostreams/detail/optional.hpp> | |
31 #include <boost/iostreams/detail/push.hpp> | |
32 #include <boost/iostreams/detail/streambuf/linked_streambuf.hpp> | |
33 #include <boost/iostreams/operations.hpp> | |
34 #include <boost/iostreams/positioning.hpp> | |
35 #include <boost/iostreams/traits.hpp> | |
36 #include <boost/iostreams/operations.hpp> | |
37 #include <boost/mpl/if.hpp> | |
38 #include <boost/throw_exception.hpp> | |
39 #include <boost/type_traits/is_convertible.hpp> | |
40 | |
41 // Must come last. | |
42 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC, BCC 5.x | |
43 | |
44 namespace boost { namespace iostreams { namespace detail { | |
45 | |
46 // | |
47 // Description: The implementation of basic_streambuf used by chains. | |
48 // | |
49 template<typename T, typename Tr, typename Alloc, typename Mode> | |
50 class indirect_streambuf | |
51 : public linked_streambuf<BOOST_DEDUCED_TYPENAME char_type_of<T>::type, Tr> | |
52 { | |
53 public: | |
54 typedef typename char_type_of<T>::type char_type; | |
55 BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) | |
56 private: | |
57 typedef typename category_of<T>::type category; | |
58 typedef concept_adapter<T> wrapper; | |
59 typedef detail::basic_buffer<char_type, Alloc> buffer_type; | |
60 typedef indirect_streambuf<T, Tr, Alloc, Mode> my_type; | |
61 typedef detail::linked_streambuf<char_type, traits_type> base_type; | |
62 typedef linked_streambuf<char_type, Tr> streambuf_type; | |
63 public: | |
64 indirect_streambuf(); | |
65 | |
66 void open(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()); | |
67 bool is_open() const; | |
68 void close(); | |
69 bool auto_close() const; | |
70 void set_auto_close(bool close); | |
71 bool strict_sync(); | |
72 | |
73 // Declared in linked_streambuf. | |
74 T* component() { return &*obj(); } | |
75 protected: | |
76 #if !BOOST_WORKAROUND(__GNUC__, == 2) | |
77 BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type) | |
78 #endif | |
79 | |
80 //----------virtual functions---------------------------------------------// | |
81 | |
82 #ifndef BOOST_IOSTREAMS_NO_LOCALE | |
83 void imbue(const std::locale& loc); | |
84 #endif | |
85 #ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES | |
86 public: | |
87 #endif | |
88 int_type underflow(); | |
89 int_type pbackfail(int_type c); | |
90 int_type overflow(int_type c); | |
91 int sync(); | |
92 pos_type seekoff( off_type off, BOOST_IOS::seekdir way, | |
93 BOOST_IOS::openmode which ); | |
94 pos_type seekpos(pos_type sp, BOOST_IOS::openmode which); | |
95 | |
96 // Declared in linked_streambuf. | |
97 void set_next(streambuf_type* next); | |
98 void close_impl(BOOST_IOS::openmode m); | |
99 const std::type_info& component_type() const { return typeid(T); } | |
100 void* component_impl() { return component(); } | |
101 private: | |
102 | |
103 //----------Accessor functions--------------------------------------------// | |
104 | |
105 wrapper& obj() { return *storage_; } | |
106 streambuf_type* next() const { return next_; } | |
107 buffer_type& in() { return buffer_.first(); } | |
108 buffer_type& out() { return buffer_.second(); } | |
109 bool can_read() const { return is_convertible<Mode, input>::value; } | |
110 bool can_write() const { return is_convertible<Mode, output>::value; } | |
111 bool output_buffered() const { return (flags_ & f_output_buffered) != 0; } | |
112 bool shared_buffer() const { return is_convertible<Mode, seekable>::value; } | |
113 void set_flags(int f) { flags_ = f; } | |
114 | |
115 //----------State changing functions--------------------------------------// | |
116 | |
117 virtual void init_get_area(); | |
118 virtual void init_put_area(); | |
119 | |
120 //----------Utility function----------------------------------------------// | |
121 | |
122 pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way, | |
123 BOOST_IOS::openmode which ); | |
124 void sync_impl(); | |
125 | |
126 enum flag_type { | |
127 f_open = 1, | |
128 f_output_buffered = f_open << 1, | |
129 f_auto_close = f_output_buffered << 1 | |
130 }; | |
131 | |
132 optional<wrapper> storage_; | |
133 streambuf_type* next_; | |
134 double_object< | |
135 buffer_type, | |
136 is_convertible< | |
137 Mode, | |
138 two_sequence | |
139 > | |
140 > buffer_; | |
141 std::streamsize pback_size_; | |
142 int flags_; | |
143 }; | |
144 | |
145 //--------------Implementation of indirect_streambuf--------------------------// | |
146 | |
147 template<typename T, typename Tr, typename Alloc, typename Mode> | |
148 indirect_streambuf<T, Tr, Alloc, Mode>::indirect_streambuf() | |
149 : next_(0), pback_size_(0), flags_(f_auto_close) { } | |
150 | |
151 //--------------Implementation of open, is_open and close---------------------// | |
152 | |
153 template<typename T, typename Tr, typename Alloc, typename Mode> | |
154 void indirect_streambuf<T, Tr, Alloc, Mode>::open | |
155 (const T& t, std::streamsize buffer_size, std::streamsize pback_size) | |
156 { | |
157 using namespace std; | |
158 | |
159 // Normalize buffer sizes. | |
160 buffer_size = | |
161 (buffer_size != -1) ? | |
162 buffer_size : | |
163 iostreams::optimal_buffer_size(t); | |
164 pback_size = | |
165 (pback_size != -1) ? | |
166 pback_size : | |
167 default_pback_buffer_size; | |
168 | |
169 // Construct input buffer. | |
170 if (can_read()) { | |
171 pback_size_ = (std::max)(std::streamsize(2), pback_size); // STLPort needs 2. | |
172 std::streamsize size = | |
173 pback_size_ + | |
174 ( buffer_size ? buffer_size: 1 ); | |
175 in().resize(size); | |
176 if (!shared_buffer()) | |
177 init_get_area(); | |
178 } | |
179 | |
180 // Construct output buffer. | |
181 if (can_write() && !shared_buffer()) { | |
182 if (buffer_size != 0) | |
183 out().resize(buffer_size); | |
184 init_put_area(); | |
185 } | |
186 | |
187 storage_.reset(wrapper(t)); | |
188 flags_ |= f_open; | |
189 if (can_write() && buffer_size > 1) | |
190 flags_ |= f_output_buffered; | |
191 this->set_true_eof(false); | |
192 this->set_needs_close(); | |
193 } | |
194 | |
195 template<typename T, typename Tr, typename Alloc, typename Mode> | |
196 inline bool indirect_streambuf<T, Tr, Alloc, Mode>::is_open() const | |
197 { return (flags_ & f_open) != 0; } | |
198 | |
199 template<typename T, typename Tr, typename Alloc, typename Mode> | |
200 void indirect_streambuf<T, Tr, Alloc, Mode>::close() | |
201 { | |
202 using namespace std; | |
203 base_type* self = this; | |
204 detail::execute_all( | |
205 detail::call_member_close(*self, BOOST_IOS::in), | |
206 detail::call_member_close(*self, BOOST_IOS::out), | |
207 detail::call_reset(storage_), | |
208 detail::clear_flags(flags_) | |
209 ); | |
210 } | |
211 | |
212 template<typename T, typename Tr, typename Alloc, typename Mode> | |
213 bool indirect_streambuf<T, Tr, Alloc, Mode>::auto_close() const | |
214 { return (flags_ & f_auto_close) != 0; } | |
215 | |
216 template<typename T, typename Tr, typename Alloc, typename Mode> | |
217 void indirect_streambuf<T, Tr, Alloc, Mode>::set_auto_close(bool close) | |
218 { flags_ = (flags_ & ~f_auto_close) | (close ? f_auto_close : 0); } | |
219 | |
220 //--------------Implementation virtual functions------------------------------// | |
221 | |
222 #ifndef BOOST_IOSTREAMS_NO_LOCALE | |
223 template<typename T, typename Tr, typename Alloc, typename Mode> | |
224 void indirect_streambuf<T, Tr, Alloc, Mode>::imbue(const std::locale& loc) | |
225 { | |
226 if (is_open()) { | |
227 obj().imbue(loc); | |
228 if (next_) | |
229 next_->pubimbue(loc); | |
230 } | |
231 } | |
232 #endif | |
233 | |
234 template<typename T, typename Tr, typename Alloc, typename Mode> | |
235 typename indirect_streambuf<T, Tr, Alloc, Mode>::int_type | |
236 indirect_streambuf<T, Tr, Alloc, Mode>::underflow() | |
237 { | |
238 using namespace std; | |
239 if (!gptr()) init_get_area(); | |
240 buffer_type& buf = in(); | |
241 if (gptr() < egptr()) return traits_type::to_int_type(*gptr()); | |
242 | |
243 // Fill putback buffer. | |
244 std::streamsize keep = | |
245 (std::min)( static_cast<std::streamsize>(gptr() - eback()), | |
246 pback_size_ ); | |
247 if (keep) | |
248 traits_type::move( buf.data() + (pback_size_ - keep), | |
249 gptr() - keep, keep ); | |
250 | |
251 // Set pointers to reasonable values in case read throws. | |
252 setg( buf.data() + pback_size_ - keep, | |
253 buf.data() + pback_size_, | |
254 buf.data() + pback_size_ ); | |
255 | |
256 // Read from source. | |
257 std::streamsize chars = | |
258 obj().read(buf.data() + pback_size_, buf.size() - pback_size_, next_); | |
259 if (chars == -1) { | |
260 this->set_true_eof(true); | |
261 chars = 0; | |
262 } | |
263 setg(eback(), gptr(), buf.data() + pback_size_ + chars); | |
264 return chars != 0 ? | |
265 traits_type::to_int_type(*gptr()) : | |
266 traits_type::eof(); | |
267 } | |
268 | |
269 template<typename T, typename Tr, typename Alloc, typename Mode> | |
270 typename indirect_streambuf<T, Tr, Alloc, Mode>::int_type | |
271 indirect_streambuf<T, Tr, Alloc, Mode>::pbackfail(int_type c) | |
272 { | |
273 if (gptr() != eback()) { | |
274 gbump(-1); | |
275 if (!traits_type::eq_int_type(c, traits_type::eof())) | |
276 *gptr() = traits_type::to_char_type(c); | |
277 return traits_type::not_eof(c); | |
278 } else { | |
279 boost::throw_exception(bad_putback()); | |
280 } | |
281 } | |
282 | |
283 template<typename T, typename Tr, typename Alloc, typename Mode> | |
284 typename indirect_streambuf<T, Tr, Alloc, Mode>::int_type | |
285 indirect_streambuf<T, Tr, Alloc, Mode>::overflow(int_type c) | |
286 { | |
287 if ( (output_buffered() && pptr() == 0) || | |
288 (shared_buffer() && gptr() != 0) ) | |
289 { | |
290 init_put_area(); | |
291 } | |
292 if (!traits_type::eq_int_type(c, traits_type::eof())) { | |
293 if (output_buffered()) { | |
294 if (pptr() == epptr()) { | |
295 sync_impl(); | |
296 if (pptr() == epptr()) | |
297 return traits_type::eof(); | |
298 } | |
299 *pptr() = traits_type::to_char_type(c); | |
300 pbump(1); | |
301 } else { | |
302 char_type d = traits_type::to_char_type(c); | |
303 if (obj().write(&d, 1, next_) != 1) | |
304 return traits_type::eof(); | |
305 } | |
306 } | |
307 return traits_type::not_eof(c); | |
308 } | |
309 | |
310 template<typename T, typename Tr, typename Alloc, typename Mode> | |
311 int indirect_streambuf<T, Tr, Alloc, Mode>::sync() | |
312 { | |
313 try { // sync() is no-throw. | |
314 sync_impl(); | |
315 obj().flush(next_); | |
316 return 0; | |
317 } catch (...) { return -1; } | |
318 } | |
319 | |
320 template<typename T, typename Tr, typename Alloc, typename Mode> | |
321 bool indirect_streambuf<T, Tr, Alloc, Mode>::strict_sync() | |
322 { | |
323 try { // sync() is no-throw. | |
324 sync_impl(); | |
325 return obj().flush(next_); | |
326 } catch (...) { return false; } | |
327 } | |
328 | |
329 template<typename T, typename Tr, typename Alloc, typename Mode> | |
330 inline typename indirect_streambuf<T, Tr, Alloc, Mode>::pos_type | |
331 indirect_streambuf<T, Tr, Alloc, Mode>::seekoff | |
332 (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) | |
333 { return seek_impl(off, way, which); } | |
334 | |
335 template<typename T, typename Tr, typename Alloc, typename Mode> | |
336 inline typename indirect_streambuf<T, Tr, Alloc, Mode>::pos_type | |
337 indirect_streambuf<T, Tr, Alloc, Mode>::seekpos | |
338 (pos_type sp, BOOST_IOS::openmode which) | |
339 { | |
340 return seek_impl(position_to_offset(sp), BOOST_IOS::beg, which); | |
341 } | |
342 | |
343 template<typename T, typename Tr, typename Alloc, typename Mode> | |
344 typename indirect_streambuf<T, Tr, Alloc, Mode>::pos_type | |
345 indirect_streambuf<T, Tr, Alloc, Mode>::seek_impl | |
346 (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which) | |
347 { | |
348 if ( gptr() != 0 && way == BOOST_IOS::cur && which == BOOST_IOS::in && | |
349 eback() - gptr() <= off && off <= egptr() - gptr() ) | |
350 { // Small seek optimization | |
351 gbump(off); | |
352 return obj().seek(0, BOOST_IOS::cur, BOOST_IOS::in, next_) - | |
353 static_cast<off_type>(egptr() - gptr()); | |
354 } | |
355 if (pptr() != 0) | |
356 this->BOOST_IOSTREAMS_PUBSYNC(); // sync() confuses VisualAge 6. | |
357 if (way == BOOST_IOS::cur && gptr()) | |
358 off -= static_cast<off_type>(egptr() - gptr()); | |
359 setg(0, 0, 0); | |
360 setp(0, 0); | |
361 return obj().seek(off, way, which, next_); | |
362 } | |
363 | |
364 template<typename T, typename Tr, typename Alloc, typename Mode> | |
365 inline void indirect_streambuf<T, Tr, Alloc, Mode>::set_next | |
366 (streambuf_type* next) | |
367 { next_ = next; } | |
368 | |
369 template<typename T, typename Tr, typename Alloc, typename Mode> | |
370 inline void indirect_streambuf<T, Tr, Alloc, Mode>::close_impl | |
371 (BOOST_IOS::openmode which) | |
372 { | |
373 if (which == BOOST_IOS::in && is_convertible<Mode, input>::value) { | |
374 setg(0, 0, 0); | |
375 } | |
376 if (which == BOOST_IOS::out && is_convertible<Mode, output>::value) { | |
377 sync(); | |
378 setp(0, 0); | |
379 } | |
380 if ( !is_convertible<category, dual_use>::value || | |
381 is_convertible<Mode, input>::value == (which == BOOST_IOS::in) ) | |
382 { | |
383 obj().close(which, next_); | |
384 } | |
385 } | |
386 | |
387 //----------State changing functions------------------------------------------// | |
388 | |
389 template<typename T, typename Tr, typename Alloc, typename Mode> | |
390 void indirect_streambuf<T, Tr, Alloc, Mode>::sync_impl() | |
391 { | |
392 std::streamsize avail, amt; | |
393 if ((avail = static_cast<std::streamsize>(pptr() - pbase())) > 0) { | |
394 if ((amt = obj().write(pbase(), avail, next())) == avail) | |
395 setp(out().begin(), out().end()); | |
396 else { | |
397 const char_type* ptr = pptr(); | |
398 setp(out().begin() + amt, out().end()); | |
399 pbump(ptr - pptr()); | |
400 } | |
401 } | |
402 } | |
403 | |
404 template<typename T, typename Tr, typename Alloc, typename Mode> | |
405 void indirect_streambuf<T, Tr, Alloc, Mode>::init_get_area() | |
406 { | |
407 if (shared_buffer() && pptr() != 0) { | |
408 sync_impl(); | |
409 setp(0, 0); | |
410 } | |
411 setg(in().begin(), in().begin(), in().begin()); | |
412 } | |
413 | |
414 template<typename T, typename Tr, typename Alloc, typename Mode> | |
415 void indirect_streambuf<T, Tr, Alloc, Mode>::init_put_area() | |
416 { | |
417 using namespace std; | |
418 if (shared_buffer() && gptr() != 0) | |
419 setg(0, 0, 0); | |
420 if (output_buffered()) | |
421 setp(out().begin(), out().end()); | |
422 else | |
423 setp(0, 0); | |
424 } | |
425 | |
426 //----------------------------------------------------------------------------// | |
427 | |
428 } } } // End namespaces detail, iostreams, boost. | |
429 | |
430 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC, BCC 5.x | |
431 | |
432 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_INDIRECT_STREAMBUF_HPP_INCLUDED |