annotate DEPENDENCIES/generic/include/boost/iostreams/chain.hpp @ 133:4acb5d8d80b6 tip

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