Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/iostreams/chain.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 | |
6 // See http://www.boost.org/libs/iostreams for documentation. | |
7 | |
8 #ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED | |
9 #define BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED | |
10 | |
11 #if defined(_MSC_VER) && (_MSC_VER >= 1020) | |
12 # pragma once | |
13 #endif | |
14 | |
15 #include <boost/assert.hpp> | |
16 #include <exception> | |
17 #include <functional> // unary_function. | |
18 #include <iterator> // advance. | |
19 #include <list> | |
20 #include <memory> // allocator, auto_ptr. | |
21 #include <typeinfo> | |
22 #include <stdexcept> // logic_error, out_of_range. | |
23 #include <boost/checked_delete.hpp> | |
24 #include <boost/config.hpp> // BOOST_MSVC, template friends, | |
25 #include <boost/detail/workaround.hpp> // BOOST_NESTED_TEMPLATE | |
26 #include <boost/iostreams/constants.hpp> | |
27 #include <boost/iostreams/detail/access_control.hpp> | |
28 #include <boost/iostreams/detail/char_traits.hpp> | |
29 #include <boost/iostreams/detail/push.hpp> | |
30 #include <boost/iostreams/detail/streambuf.hpp> // pubsync. | |
31 #include <boost/iostreams/detail/wrap_unwrap.hpp> | |
32 #include <boost/iostreams/device/null.hpp> | |
33 #include <boost/iostreams/positioning.hpp> | |
34 #include <boost/iostreams/traits.hpp> // is_filter. | |
35 #include <boost/iostreams/stream_buffer.hpp> | |
36 #include <boost/next_prior.hpp> | |
37 #include <boost/shared_ptr.hpp> | |
38 #include <boost/static_assert.hpp> | |
39 #include <boost/throw_exception.hpp> | |
40 #include <boost/type_traits/is_convertible.hpp> | |
41 #include <boost/type.hpp> | |
42 #include <boost/iostreams/detail/execute.hpp> // VC6.5 requires this | |
43 #if BOOST_WORKAROUND(BOOST_MSVC, < 1310) // #include order | |
44 # include <boost/mpl/int.hpp> | |
45 #endif | |
46 | |
47 // Sometimes type_info objects must be compared by name. Borrowed from | |
48 // Boost.Python and Boost.Function. | |
49 #if (defined(__GNUC__) && __GNUC__ >= 3) || \ | |
50 defined(_AIX) || \ | |
51 (defined(__sgi) && defined(__host_mips)) || \ | |
52 (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC)) \ | |
53 /**/ | |
54 # include <cstring> | |
55 # define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) \ | |
56 (std::strcmp((X).name(),(Y).name()) == 0) | |
57 #else | |
58 # define BOOST_IOSTREAMS_COMPARE_TYPE_ID(X,Y) ((X)==(Y)) | |
59 #endif | |
60 | |
61 // Deprecated | |
62 #define BOOST_IOSTREAMS_COMPONENT_TYPE(chain, index) \ | |
63 chain.component_type( index ) \ | |
64 /**/ | |
65 | |
66 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) | |
67 # define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \ | |
68 chain.component< target >( index ) \ | |
69 /**/ | |
70 #else | |
71 # define BOOST_IOSTREAMS_COMPONENT(chain, index, target) \ | |
72 chain.component( index, ::boost::type< target >() ) \ | |
73 /**/ | |
74 #endif | |
75 | |
76 namespace boost { namespace iostreams { | |
77 | |
78 //--------------Definition of chain and wchain--------------------------------// | |
79 | |
80 namespace detail { | |
81 | |
82 template<typename Chain> class chain_client; | |
83 | |
84 // | |
85 // Concept name: Chain. | |
86 // Description: Represents a chain of stream buffers which provides access | |
87 // to the first buffer in the chain and sends notifications when the | |
88 // streambufs are added to or removed from chain. | |
89 // Refines: Closable device with mode equal to typename Chain::mode. | |
90 // Models: chain, converting_chain. | |
91 // Example: | |
92 // | |
93 // class chain { | |
94 // public: | |
95 // typedef xxx chain_type; | |
96 // typedef xxx client_type; | |
97 // typedef xxx mode; | |
98 // bool is_complete() const; // Ready for i/o. | |
99 // template<typename T> | |
100 // void push( const T& t, // Adds a stream buffer to | |
101 // streamsize, // chain, based on t, with | |
102 // streamsize ); // given buffer and putback | |
103 // // buffer sizes. Pass -1 to | |
104 // // request default size. | |
105 // protected: | |
106 // void register_client(client_type* client); // Associate client. | |
107 // void notify(); // Notify client. | |
108 // }; | |
109 // | |
110 | |
111 // | |
112 // Description: Represents a chain of filters with an optional device at the | |
113 // end. | |
114 // Template parameters: | |
115 // Self - A class deriving from the current instantiation of this template. | |
116 // This is an example of the Curiously Recurring Template Pattern. | |
117 // Ch - The character type. | |
118 // Tr - The character traits type. | |
119 // Alloc - The allocator type. | |
120 // Mode - A mode tag. | |
121 // | |
122 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
123 class chain_base { | |
124 public: | |
125 typedef Ch char_type; | |
126 BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr) | |
127 typedef Alloc allocator_type; | |
128 typedef Mode mode; | |
129 struct category | |
130 : Mode, | |
131 device_tag | |
132 { }; | |
133 typedef chain_client<Self> client_type; | |
134 friend class chain_client<Self>; | |
135 private: | |
136 typedef linked_streambuf<Ch> streambuf_type; | |
137 typedef std::list<streambuf_type*> list_type; | |
138 typedef chain_base<Self, Ch, Tr, Alloc, Mode> my_type; | |
139 protected: | |
140 chain_base() : pimpl_(new chain_impl) { } | |
141 chain_base(const chain_base& rhs): pimpl_(rhs.pimpl_) { } | |
142 public: | |
143 | |
144 // dual_use is a pseudo-mode to facilitate filter writing, | |
145 // not a genuine mode. | |
146 BOOST_STATIC_ASSERT((!is_convertible<mode, dual_use>::value)); | |
147 | |
148 //----------Buffer sizing-------------------------------------------------// | |
149 | |
150 // Sets the size of the buffer created for the devices to be added to this | |
151 // chain. Does not affect the size of the buffer for devices already | |
152 // added. | |
153 void set_device_buffer_size(std::streamsize n) | |
154 { pimpl_->device_buffer_size_ = n; } | |
155 | |
156 // Sets the size of the buffer created for the filters to be added | |
157 // to this chain. Does not affect the size of the buffer for filters already | |
158 // added. | |
159 void set_filter_buffer_size(std::streamsize n) | |
160 { pimpl_->filter_buffer_size_ = n; } | |
161 | |
162 // Sets the size of the putback buffer for filters and devices to be added | |
163 // to this chain. Does not affect the size of the buffer for filters or | |
164 // devices already added. | |
165 void set_pback_size(std::streamsize n) | |
166 { pimpl_->pback_size_ = n; } | |
167 | |
168 //----------Device interface----------------------------------------------// | |
169 | |
170 std::streamsize read(char_type* s, std::streamsize n); | |
171 std::streamsize write(const char_type* s, std::streamsize n); | |
172 std::streampos seek(stream_offset off, BOOST_IOS::seekdir way); | |
173 | |
174 //----------Direct component access---------------------------------------// | |
175 | |
176 const std::type_info& component_type(int n) const | |
177 { | |
178 if (static_cast<size_type>(n) >= size()) | |
179 boost::throw_exception(std::out_of_range("bad chain offset")); | |
180 return (*boost::next(list().begin(), n))->component_type(); | |
181 } | |
182 | |
183 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) | |
184 // Deprecated. | |
185 template<int N> | |
186 const std::type_info& component_type() const { return component_type(N); } | |
187 | |
188 template<typename T> | |
189 T* component(int n) const { return component(n, boost::type<T>()); } | |
190 | |
191 // Deprecated. | |
192 template<int N, typename T> | |
193 T* component() const { return component<T>(N); } | |
194 #endif | |
195 | |
196 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) | |
197 private: | |
198 #endif | |
199 template<typename T> | |
200 T* component(int n, boost::type<T>) const | |
201 { | |
202 if (static_cast<size_type>(n) >= size()) | |
203 boost::throw_exception(std::out_of_range("bad chain offset")); | |
204 streambuf_type* link = *boost::next(list().begin(), n); | |
205 if (BOOST_IOSTREAMS_COMPARE_TYPE_ID(link->component_type(), typeid(T))) | |
206 return static_cast<T*>(link->component_impl()); | |
207 else | |
208 return 0; | |
209 } | |
210 public: | |
211 | |
212 //----------Container-like interface--------------------------------------// | |
213 | |
214 typedef typename list_type::size_type size_type; | |
215 streambuf_type& front() { return *list().front(); } | |
216 BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl) | |
217 void pop(); | |
218 bool empty() const { return list().empty(); } | |
219 size_type size() const { return list().size(); } | |
220 void reset(); | |
221 | |
222 //----------Additional i/o functions--------------------------------------// | |
223 | |
224 // Returns true if this chain is non-empty and its final link | |
225 // is a source or sink, i.e., if it is ready to perform i/o. | |
226 bool is_complete() const; | |
227 bool auto_close() const; | |
228 void set_auto_close(bool close); | |
229 bool sync() { return front().BOOST_IOSTREAMS_PUBSYNC() != -1; } | |
230 bool strict_sync(); | |
231 private: | |
232 template<typename T> | |
233 void push_impl(const T& t, std::streamsize buffer_size = -1, | |
234 std::streamsize pback_size = -1) | |
235 { | |
236 typedef typename iostreams::category_of<T>::type category; | |
237 typedef typename unwrap_ios<T>::type component_type; | |
238 typedef stream_buffer< | |
239 component_type, | |
240 BOOST_IOSTREAMS_CHAR_TRAITS(char_type), | |
241 Alloc, Mode | |
242 > streambuf_t; | |
243 typedef typename list_type::iterator iterator; | |
244 BOOST_STATIC_ASSERT((is_convertible<category, Mode>::value)); | |
245 if (is_complete()) | |
246 boost::throw_exception(std::logic_error("chain complete")); | |
247 streambuf_type* prev = !empty() ? list().back() : 0; | |
248 buffer_size = | |
249 buffer_size != -1 ? | |
250 buffer_size : | |
251 iostreams::optimal_buffer_size(t); | |
252 pback_size = | |
253 pback_size != -1 ? | |
254 pback_size : | |
255 pimpl_->pback_size_; | |
256 std::auto_ptr<streambuf_t> | |
257 buf(new streambuf_t(t, buffer_size, pback_size)); | |
258 list().push_back(buf.get()); | |
259 buf.release(); | |
260 if (is_device<component_type>::value) { | |
261 pimpl_->flags_ |= f_complete | f_open; | |
262 for ( iterator first = list().begin(), | |
263 last = list().end(); | |
264 first != last; | |
265 ++first ) | |
266 { | |
267 (*first)->set_needs_close(); | |
268 } | |
269 } | |
270 if (prev) prev->set_next(list().back()); | |
271 notify(); | |
272 } | |
273 | |
274 list_type& list() { return pimpl_->links_; } | |
275 const list_type& list() const { return pimpl_->links_; } | |
276 void register_client(client_type* client) { pimpl_->client_ = client; } | |
277 void notify() { if (pimpl_->client_) pimpl_->client_->notify(); } | |
278 | |
279 //----------Nested classes------------------------------------------------// | |
280 | |
281 static void close(streambuf_type* b, BOOST_IOS::openmode m) | |
282 { | |
283 if (m == BOOST_IOS::out && is_convertible<Mode, output>::value) | |
284 b->BOOST_IOSTREAMS_PUBSYNC(); | |
285 b->close(m); | |
286 } | |
287 | |
288 static void set_next(streambuf_type* b, streambuf_type* next) | |
289 { b->set_next(next); } | |
290 | |
291 static void set_auto_close(streambuf_type* b, bool close) | |
292 { b->set_auto_close(close); } | |
293 | |
294 struct closer : public std::unary_function<streambuf_type*, void> { | |
295 closer(BOOST_IOS::openmode m) : mode_(m) { } | |
296 void operator() (streambuf_type* b) | |
297 { | |
298 close(b, mode_); | |
299 } | |
300 BOOST_IOS::openmode mode_; | |
301 }; | |
302 friend struct closer; | |
303 | |
304 enum flags { | |
305 f_complete = 1, | |
306 f_open = 2, | |
307 f_auto_close = 4 | |
308 }; | |
309 | |
310 struct chain_impl { | |
311 chain_impl() | |
312 : client_(0), device_buffer_size_(default_device_buffer_size), | |
313 filter_buffer_size_(default_filter_buffer_size), | |
314 pback_size_(default_pback_buffer_size), | |
315 flags_(f_auto_close) | |
316 { } | |
317 ~chain_impl() | |
318 { | |
319 try { close(); } catch (...) { } | |
320 try { reset(); } catch (...) { } | |
321 } | |
322 void close() | |
323 { | |
324 if ((flags_ & f_open) != 0) { | |
325 flags_ &= ~f_open; | |
326 stream_buffer< basic_null_device<Ch, Mode> > null; | |
327 if ((flags_ & f_complete) == 0) { | |
328 null.open(basic_null_device<Ch, Mode>()); | |
329 set_next(links_.back(), &null); | |
330 } | |
331 links_.front()->BOOST_IOSTREAMS_PUBSYNC(); | |
332 try { | |
333 boost::iostreams::detail::execute_foreach( | |
334 links_.rbegin(), links_.rend(), | |
335 closer(BOOST_IOS::in) | |
336 ); | |
337 } catch (...) { | |
338 try { | |
339 boost::iostreams::detail::execute_foreach( | |
340 links_.begin(), links_.end(), | |
341 closer(BOOST_IOS::out) | |
342 ); | |
343 } catch (...) { } | |
344 throw; | |
345 } | |
346 boost::iostreams::detail::execute_foreach( | |
347 links_.begin(), links_.end(), | |
348 closer(BOOST_IOS::out) | |
349 ); | |
350 } | |
351 } | |
352 void reset() | |
353 { | |
354 typedef typename list_type::iterator iterator; | |
355 for ( iterator first = links_.begin(), | |
356 last = links_.end(); | |
357 first != last; | |
358 ++first ) | |
359 { | |
360 if ( (flags_ & f_complete) == 0 || | |
361 (flags_ & f_auto_close) == 0 ) | |
362 { | |
363 set_auto_close(*first, false); | |
364 } | |
365 streambuf_type* buf = 0; | |
366 std::swap(buf, *first); | |
367 delete buf; | |
368 } | |
369 links_.clear(); | |
370 flags_ &= ~f_complete; | |
371 flags_ &= ~f_open; | |
372 } | |
373 list_type links_; | |
374 client_type* client_; | |
375 std::streamsize device_buffer_size_, | |
376 filter_buffer_size_, | |
377 pback_size_; | |
378 int flags_; | |
379 }; | |
380 friend struct chain_impl; | |
381 | |
382 //----------Member data---------------------------------------------------// | |
383 | |
384 private: | |
385 shared_ptr<chain_impl> pimpl_; | |
386 }; | |
387 | |
388 } // End namespace detail. | |
389 | |
390 // | |
391 // Macro: BOOST_IOSTREAMS_DECL_CHAIN(name, category) | |
392 // Description: Defines a template derived from chain_base appropriate for a | |
393 // particular i/o category. The template has the following parameters: | |
394 // Ch - The character type. | |
395 // Tr - The character traits type. | |
396 // Alloc - The allocator type. | |
397 // Macro parameters: | |
398 // name_ - The name of the template to be defined. | |
399 // category_ - The i/o category of the template to be defined. | |
400 // | |
401 #define BOOST_IOSTREAMS_DECL_CHAIN(name_, default_char_) \ | |
402 template< typename Mode, typename Ch = default_char_, \ | |
403 typename Tr = BOOST_IOSTREAMS_CHAR_TRAITS(Ch), \ | |
404 typename Alloc = std::allocator<Ch> > \ | |
405 class name_ : public boost::iostreams::detail::chain_base< \ | |
406 name_<Mode, Ch, Tr, Alloc>, \ | |
407 Ch, Tr, Alloc, Mode \ | |
408 > \ | |
409 { \ | |
410 public: \ | |
411 struct category : device_tag, Mode { }; \ | |
412 typedef Mode mode; \ | |
413 private: \ | |
414 typedef boost::iostreams::detail::chain_base< \ | |
415 name_<Mode, Ch, Tr, Alloc>, \ | |
416 Ch, Tr, Alloc, Mode \ | |
417 > base_type; \ | |
418 public: \ | |
419 typedef Ch char_type; \ | |
420 typedef Tr traits_type; \ | |
421 typedef typename traits_type::int_type int_type; \ | |
422 typedef typename traits_type::off_type off_type; \ | |
423 name_() { } \ | |
424 name_(const name_& rhs) : base_type(rhs) { } \ | |
425 name_& operator=(const name_& rhs) \ | |
426 { base_type::operator=(rhs); return *this; } \ | |
427 }; \ | |
428 /**/ | |
429 BOOST_IOSTREAMS_DECL_CHAIN(chain, char) | |
430 BOOST_IOSTREAMS_DECL_CHAIN(wchain, wchar_t) | |
431 #undef BOOST_IOSTREAMS_DECL_CHAIN | |
432 | |
433 //--------------Definition of chain_client------------------------------------// | |
434 | |
435 namespace detail { | |
436 | |
437 // | |
438 // Template name: chain_client | |
439 // Description: Class whose instances provide access to an underlying chain | |
440 // using an interface similar to the chains. | |
441 // Subclasses: the various stream and stream buffer templates. | |
442 // | |
443 template<typename Chain> | |
444 class chain_client { | |
445 public: | |
446 typedef Chain chain_type; | |
447 typedef typename chain_type::char_type char_type; | |
448 typedef typename chain_type::traits_type traits_type; | |
449 typedef typename chain_type::size_type size_type; | |
450 typedef typename chain_type::mode mode; | |
451 | |
452 chain_client(chain_type* chn = 0) : chain_(chn ) { } | |
453 chain_client(chain_client* client) : chain_(client->chain_) { } | |
454 virtual ~chain_client() { } | |
455 | |
456 const std::type_info& component_type(int n) const | |
457 { return chain_->component_type(n); } | |
458 | |
459 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) | |
460 // Deprecated. | |
461 template<int N> | |
462 const std::type_info& component_type() const | |
463 { return chain_->BOOST_NESTED_TEMPLATE component_type<N>(); } | |
464 | |
465 template<typename T> | |
466 T* component(int n) const | |
467 { return chain_->BOOST_NESTED_TEMPLATE component<T>(n); } | |
468 | |
469 // Deprecated. | |
470 template<int N, typename T> | |
471 T* component() const | |
472 { return chain_->BOOST_NESTED_TEMPLATE component<N, T>(); } | |
473 #else | |
474 template<typename T> | |
475 T* component(int n, boost::type<T> t) const | |
476 { return chain_->component(n, t); } | |
477 #endif | |
478 | |
479 bool is_complete() const { return chain_->is_complete(); } | |
480 bool auto_close() const { return chain_->auto_close(); } | |
481 void set_auto_close(bool close) { chain_->set_auto_close(close); } | |
482 bool strict_sync() { return chain_->strict_sync(); } | |
483 void set_device_buffer_size(std::streamsize n) | |
484 { chain_->set_device_buffer_size(n); } | |
485 void set_filter_buffer_size(std::streamsize n) | |
486 { chain_->set_filter_buffer_size(n); } | |
487 void set_pback_size(std::streamsize n) { chain_->set_pback_size(n); } | |
488 BOOST_IOSTREAMS_DEFINE_PUSH(push, mode, char_type, push_impl) | |
489 void pop() { chain_->pop(); } | |
490 bool empty() const { return chain_->empty(); } | |
491 size_type size() { return chain_->size(); } | |
492 void reset() { chain_->reset(); } | |
493 | |
494 // Returns a copy of the underlying chain. | |
495 chain_type filters() { return *chain_; } | |
496 chain_type filters() const { return *chain_; } | |
497 protected: | |
498 template<typename T> | |
499 void push_impl(const T& t BOOST_IOSTREAMS_PUSH_PARAMS()) | |
500 { chain_->push(t BOOST_IOSTREAMS_PUSH_ARGS()); } | |
501 chain_type& ref() { return *chain_; } | |
502 void set_chain(chain_type* c) | |
503 { chain_ = c; chain_->register_client(this); } | |
504 #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) && \ | |
505 (!BOOST_WORKAROUND(__BORLANDC__, < 0x600)) | |
506 template<typename S, typename C, typename T, typename A, typename M> | |
507 friend class chain_base; | |
508 #else | |
509 public: | |
510 #endif | |
511 virtual void notify() { } | |
512 private: | |
513 chain_type* chain_; | |
514 }; | |
515 | |
516 //--------------Implementation of chain_base----------------------------------// | |
517 | |
518 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
519 inline std::streamsize chain_base<Self, Ch, Tr, Alloc, Mode>::read | |
520 (char_type* s, std::streamsize n) | |
521 { return iostreams::read(*list().front(), s, n); } | |
522 | |
523 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
524 inline std::streamsize chain_base<Self, Ch, Tr, Alloc, Mode>::write | |
525 (const char_type* s, std::streamsize n) | |
526 { return iostreams::write(*list().front(), s, n); } | |
527 | |
528 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
529 inline std::streampos chain_base<Self, Ch, Tr, Alloc, Mode>::seek | |
530 (stream_offset off, BOOST_IOS::seekdir way) | |
531 { return iostreams::seek(*list().front(), off, way); } | |
532 | |
533 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
534 void chain_base<Self, Ch, Tr, Alloc, Mode>::reset() | |
535 { | |
536 using namespace std; | |
537 pimpl_->close(); | |
538 pimpl_->reset(); | |
539 } | |
540 | |
541 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
542 bool chain_base<Self, Ch, Tr, Alloc, Mode>::is_complete() const | |
543 { | |
544 return (pimpl_->flags_ & f_complete) != 0; | |
545 } | |
546 | |
547 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
548 bool chain_base<Self, Ch, Tr, Alloc, Mode>::auto_close() const | |
549 { | |
550 return (pimpl_->flags_ & f_auto_close) != 0; | |
551 } | |
552 | |
553 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
554 void chain_base<Self, Ch, Tr, Alloc, Mode>::set_auto_close(bool close) | |
555 { | |
556 pimpl_->flags_ = | |
557 (pimpl_->flags_ & ~f_auto_close) | | |
558 (close ? f_auto_close : 0); | |
559 } | |
560 | |
561 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
562 bool chain_base<Self, Ch, Tr, Alloc, Mode>::strict_sync() | |
563 { | |
564 typedef typename list_type::iterator iterator; | |
565 bool result = true; | |
566 for ( iterator first = list().begin(), | |
567 last = list().end(); | |
568 first != last; | |
569 ++first ) | |
570 { | |
571 bool s = (*first)->strict_sync(); | |
572 result = result && s; | |
573 } | |
574 return result; | |
575 } | |
576 | |
577 template<typename Self, typename Ch, typename Tr, typename Alloc, typename Mode> | |
578 void chain_base<Self, Ch, Tr, Alloc, Mode>::pop() | |
579 { | |
580 BOOST_ASSERT(!empty()); | |
581 if (auto_close()) | |
582 pimpl_->close(); | |
583 streambuf_type* buf = 0; | |
584 std::swap(buf, list().back()); | |
585 buf->set_auto_close(false); | |
586 buf->set_next(0); | |
587 delete buf; | |
588 list().pop_back(); | |
589 pimpl_->flags_ &= ~f_complete; | |
590 if (auto_close() || list().empty()) | |
591 pimpl_->flags_ &= ~f_open; | |
592 } | |
593 | |
594 } // End namespace detail. | |
595 | |
596 } } // End namespaces iostreams, boost. | |
597 | |
598 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_CHAIN_HPP_INCLUDED |