1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 //
11 // This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012.
12 // Changed internal SGI string to a generic, templatized vector. Added efficient
13 // internal buffer get/set/swap functions, so that we can obtain/establish the
14 // internal buffer without any reallocation or copy. Kill those temporaries!
15 ///////////////////////////////////////////////////////////////////////////////
16 /*
17  * Copyright (c) 1998
18  * Silicon Graphics Computer Systems, Inc.
19  *
20  * Permission to use, copy, modify, distribute and sell this software
21  * and its documentation for any purpose is hereby granted without fee,
22  * provided that the above copyright notice appear in all copies and
23  * that both that copyright notice and this permission notice appear
24  * in supporting documentation.  Silicon Graphics makes no
25  * representations about the suitability of this software for any
26  * purpose.  It is provided "as is" without express or implied warranty.
27  */
28 
29 //!\file
30 //!This file defines basic_vectorbuf, basic_ivectorstream,
31 //!basic_ovectorstream, and basic_vectorstreamclasses.  These classes
32 //!represent streamsbufs and streams whose sources or destinations are
33 //!STL-like vectors that can be swapped with external vectors to avoid
34 //!unnecessary allocations/copies.
35 
36 #ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP
37 #define BOOST_INTERPROCESS_VECTORSTREAM_HPP
38 
39 #ifndef BOOST_CONFIG_HPP
40 #  include <boost/config.hpp>
41 #endif
42 #
43 #if defined(BOOST_HAS_PRAGMA_ONCE)
44 #  pragma once
45 #endif
46 
47 #include <boost/interprocess/detail/config_begin.hpp>
48 #include <boost/interprocess/detail/workaround.hpp>
49 
50 #include <iosfwd>
51 #include <ios>
52 #include <istream>
53 #include <ostream>
54 #include <string>    // char traits
55 #include <cstddef>   // ptrdiff_t
56 #include <boost/interprocess/interprocess_fwd.hpp>
57 #include <boost/assert.hpp>
58 
59 namespace boost {  namespace interprocess {
60 
61 //!A streambuf class that controls the transmission of elements to and from
62 //!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream.
63 //!It holds a character vector specified by CharVector template parameter
64 //!as its formatting buffer. The vector must have contiguous storage, like
65 //!std::vector, boost::interprocess::vector or boost::interprocess::basic_string
66 template <class CharVector, class CharTraits>
67 class basic_vectorbuf
68    : public std::basic_streambuf<typename CharVector::value_type, CharTraits>
69 {
70    public:
71    typedef CharVector                        vector_type;
72    typedef typename CharVector::value_type   char_type;
73    typedef typename CharTraits::int_type     int_type;
74    typedef typename CharTraits::pos_type     pos_type;
75    typedef typename CharTraits::off_type     off_type;
76    typedef CharTraits                        traits_type;
77 
78    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
79    private:
80    typedef std::basic_streambuf<char_type, traits_type> base_t;
81 
82    basic_vectorbuf(const basic_vectorbuf&);
83    basic_vectorbuf & operator =(const basic_vectorbuf&);
84    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
85 
86    public:
87    //!Constructor. Throws if vector_type default
88    //!constructor throws.
basic_vectorbuf(std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)89    explicit basic_vectorbuf(std::ios_base::openmode mode
90                               = std::ios_base::in | std::ios_base::out)
91       :  base_t(), m_mode(mode)
92    {  this->initialize_pointers();   }
93 
94    //!Constructor. Throws if
95    //!vector_type(const VectorParameter &param) throws.
96    template<class VectorParameter>
basic_vectorbuf(const VectorParameter & param,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)97    explicit basic_vectorbuf(const VectorParameter &param,
98                             std::ios_base::openmode mode
99                                  = std::ios_base::in | std::ios_base::out)
100       :  base_t(), m_mode(mode), m_vect(param)
101    {  this->initialize_pointers();   }
102 
103    public:
104 
105    //!Swaps the underlying vector with the passed vector.
106    //!This function resets the read/write position in the stream.
107    //!Does not throw.
swap_vector(vector_type & vect)108    void swap_vector(vector_type &vect)
109    {
110       if (this->m_mode & std::ios_base::out){
111          //Update high water if necessary
112          //And resize vector to remove extra size
113          if (mp_high_water < base_t::pptr()){
114             //Restore the vector's size if necessary
115             mp_high_water = base_t::pptr();
116          }
117          //This does not reallocate
118          m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0));
119       }
120       //Now swap vector
121       m_vect.swap(vect);
122       this->initialize_pointers();
123    }
124 
125    //!Returns a const reference to the internal vector.
126    //!Does not throw.
vector() const127    const vector_type &vector() const
128    {
129       if (this->m_mode & std::ios_base::out){
130          if (mp_high_water < base_t::pptr()){
131             //Restore the vector's size if necessary
132             mp_high_water = base_t::pptr();
133          }
134          //This shouldn't reallocate
135          typedef typename vector_type::size_type size_type;
136          char_type *old_ptr = base_t::pbase();
137          size_type high_pos = size_type(mp_high_water-old_ptr);
138          if(m_vect.size() > high_pos){
139             m_vect.resize(high_pos);
140             //But we must update end write pointer because vector size is now shorter
141             int old_pos = base_t::pptr() - base_t::pbase();
142             const_cast<basic_vectorbuf*>(this)->base_t::setp(old_ptr, old_ptr + high_pos);
143             const_cast<basic_vectorbuf*>(this)->base_t::pbump(old_pos);
144          }
145       }
146       return m_vect;
147    }
148 
149    //!Preallocates memory from the internal vector.
150    //!Resets the stream to the first position.
151    //!Throws if the internals vector's memory allocation throws.
reserve(typename vector_type::size_type size)152    void reserve(typename vector_type::size_type size)
153    {
154       if (this->m_mode & std::ios_base::out && size > m_vect.size()){
155          typename vector_type::difference_type write_pos = base_t::pptr() - base_t::pbase();
156          typename vector_type::difference_type read_pos  = base_t::gptr() - base_t::eback();
157          //Now update pointer data
158          m_vect.reserve(size);
159          this->initialize_pointers();
160          base_t::pbump((int)write_pos);
161          if(this->m_mode & std::ios_base::in){
162             base_t::gbump((int)read_pos);
163          }
164       }
165    }
166 
167    //!Calls clear() method of the internal vector.
168    //!Resets the stream to the first position.
clear()169    void clear()
170    {  m_vect.clear();   this->initialize_pointers();   }
171 
172    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
173    private:
174    //Maximizes high watermark to the initial vector size,
175    //initializes read and write iostream buffers to the capacity
176    //and resets stream positions
initialize_pointers()177    void initialize_pointers()
178    {
179       // The initial read position is the beginning of the vector.
180       if(!(m_mode & std::ios_base::out)){
181          if(m_vect.empty()){
182             this->setg(0, 0, 0);
183          }
184          else{
185             this->setg(&m_vect[0], &m_vect[0], &m_vect[0] + m_vect.size());
186          }
187       }
188 
189       // The initial write position is the beginning of the vector.
190       if(m_mode & std::ios_base::out){
191          //First get real size
192          int real_size = (int)m_vect.size();
193          //Then maximize size for high watermarking
194          m_vect.resize(m_vect.capacity());
195          BOOST_ASSERT(m_vect.size() == m_vect.capacity());
196          //Set high watermarking with the expanded size
197          mp_high_water = m_vect.size() ? (&m_vect[0] + real_size) : 0;
198          //Now set formatting pointers
199          if(m_vect.empty()){
200             this->setp(0, 0);
201             if(m_mode & std::ios_base::in)
202                this->setg(0, 0, 0);
203          }
204          else{
205             char_type *p = &m_vect[0];
206             this->setp(p, p + m_vect.size());
207             if(m_mode & std::ios_base::in)
208                this->setg(p, p, p + real_size);
209          }
210          if (m_mode & (std::ios_base::app | std::ios_base::ate)){
211             base_t::pbump((int)real_size);
212          }
213       }
214    }
215 
216    protected:
underflow()217    virtual int_type underflow()
218    {
219       if (base_t::gptr() == 0)
220          return CharTraits::eof();
221       if(m_mode & std::ios_base::out){
222          if (mp_high_water < base_t::pptr())
223             mp_high_water = base_t::pptr();
224          if (base_t::egptr() < mp_high_water)
225             base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water);
226       }
227       if (base_t::gptr() < base_t::egptr())
228          return CharTraits::to_int_type(*base_t::gptr());
229       return CharTraits::eof();
230    }
231 
pbackfail(int_type c=CharTraits::eof ())232    virtual int_type pbackfail(int_type c = CharTraits::eof())
233    {
234       if(this->gptr() != this->eback()) {
235          if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
236             if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) {
237                this->gbump(-1);
238                return c;
239             }
240             else if(m_mode & std::ios_base::out) {
241                this->gbump(-1);
242                *this->gptr() = c;
243                return c;
244             }
245             else
246                return CharTraits::eof();
247          }
248          else {
249             this->gbump(-1);
250             return CharTraits::not_eof(c);
251          }
252       }
253       else
254          return CharTraits::eof();
255    }
256 
overflow(int_type c=CharTraits::eof ())257    virtual int_type overflow(int_type c = CharTraits::eof())
258    {
259       if(m_mode & std::ios_base::out) {
260          if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
261                typedef typename vector_type::difference_type dif_t;
262                //The new output position is the previous one plus one
263                //because 'overflow' requires putting 'c' on the buffer
264                dif_t new_outpos = base_t::pptr() - base_t::pbase() + 1;
265                //Adjust high water if necessary
266                dif_t hipos = mp_high_water - base_t::pbase();
267                if (hipos < new_outpos)
268                   hipos = new_outpos;
269                //Insert the new data
270                m_vect.push_back(CharTraits::to_char_type(c));
271                m_vect.resize(m_vect.capacity());
272                BOOST_ASSERT(m_vect.size() == m_vect.capacity());
273                char_type* p = const_cast<char_type*>(&m_vect[0]);
274                //A reallocation might have happened, update pointers
275                base_t::setp(p, p + (dif_t)m_vect.size());
276                mp_high_water = p + hipos;
277                if (m_mode & std::ios_base::in)
278                   base_t::setg(p, p + (base_t::gptr() - base_t::eback()), mp_high_water);
279                //Update write position to the old position + 1
280                base_t::pbump((int)new_outpos);
281                return c;
282          }
283          else  // c is EOF, so we don't have to do anything
284             return CharTraits::not_eof(c);
285       }
286       else     // Overflow always fails if it's read-only.
287          return CharTraits::eof();
288    }
289 
seekoff(off_type off,std::ios_base::seekdir dir,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)290    virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir,
291                               std::ios_base::openmode mode
292                                  = std::ios_base::in | std::ios_base::out)
293    {
294       //Get seek mode
295       bool in(0 != (mode & std::ios_base::in)), out(0 != (mode & std::ios_base::out));
296       //Test for logic errors
297       if(!in & !out)
298          return pos_type(off_type(-1));
299       else if((in && out) && (dir == std::ios_base::cur))
300          return pos_type(off_type(-1));
301       else if((in  && (!(m_mode & std::ios_base::in) || (off != 0 && this->gptr() == 0) )) ||
302                (out && (!(m_mode & std::ios_base::out) || (off != 0 && this->pptr() == 0))))
303          return pos_type(off_type(-1));
304 
305       off_type newoff;
306       //Just calculate the end of the stream. If the stream is read-only
307       //the limit is the size of the vector. Otherwise, the high water mark
308       //will mark the real size.
309       off_type limit;
310       if(m_mode & std::ios_base::out){
311          //Update high water marking because pptr() is going to change and it might
312          //have been updated since last overflow()
313          if(mp_high_water < base_t::pptr())
314             mp_high_water = base_t::pptr();
315          //Update read limits in case high water mark was changed
316          if(m_mode & std::ios_base::in){
317             if (base_t::egptr() < mp_high_water)
318                base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water);
319          }
320          limit = static_cast<off_type>(mp_high_water - base_t::pbase());
321       }
322       else{
323          limit = static_cast<off_type>(m_vect.size());
324       }
325 
326       switch(dir) {
327          case std::ios_base::beg:
328             newoff = 0;
329          break;
330          case std::ios_base::end:
331             newoff = limit;
332          break;
333          case std::ios_base::cur:
334             newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback())
335                         : static_cast<std::streamoff>(this->pptr() - this->pbase());
336          break;
337          default:
338             return pos_type(off_type(-1));
339       }
340 
341       newoff += off;
342 
343       if (newoff < 0 || newoff > limit)
344          return pos_type(-1);
345       if (m_mode & std::ios_base::app && mode & std::ios_base::out && newoff != limit)
346          return pos_type(-1);
347       //This can reassign pointers
348       //if(m_vect.size() != m_vect.capacity())
349          //this->initialize_pointers();
350       if (in)
351          base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr());
352       if (out){
353          base_t::setp(base_t::pbase(), base_t::epptr());
354          base_t::pbump(newoff);
355       }
356       return pos_type(newoff);
357    }
358 
seekpos(pos_type pos,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)359    virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode
360                                  = std::ios_base::in | std::ios_base::out)
361    {  return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode);  }
362 
363    private:
364    std::ios_base::openmode m_mode;
365    mutable vector_type     m_vect;
366    mutable char_type*      mp_high_water;
367    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
368 };
369 
370 //!A basic_istream class that holds a character vector specified by CharVector
371 //!template parameter as its formatting buffer. The vector must have
372 //!contiguous storage, like std::vector, boost::interprocess::vector or
373 //!boost::interprocess::basic_string
374 template <class CharVector, class CharTraits>
375 class basic_ivectorstream
376    : public std::basic_istream<typename CharVector::value_type, CharTraits>
377    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
378    , private basic_vectorbuf<CharVector, CharTraits>
379    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
380 {
381    public:
382    typedef CharVector                                                   vector_type;
383    typedef typename std::basic_ios
384       <typename CharVector::value_type, CharTraits>::char_type          char_type;
385    typedef typename std::basic_ios<char_type, CharTraits>::int_type     int_type;
386    typedef typename std::basic_ios<char_type, CharTraits>::pos_type     pos_type;
387    typedef typename std::basic_ios<char_type, CharTraits>::off_type     off_type;
388    typedef typename std::basic_ios<char_type, CharTraits>::traits_type  traits_type;
389 
390    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
391    private:
392    typedef basic_vectorbuf<CharVector, CharTraits>    vectorbuf_t;
393    typedef std::basic_ios<char_type, CharTraits>      basic_ios_t;
394    typedef std::basic_istream<char_type, CharTraits>  base_t;
395 
get_buf()396    vectorbuf_t &       get_buf()      {  return *this;  }
get_buf() const397    const vectorbuf_t & get_buf() const{  return *this;  }
398    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
399 
400    public:
401 
402    //!Constructor. Throws if vector_type default
403    //!constructor throws.
basic_ivectorstream(std::ios_base::openmode mode=std::ios_base::in)404    basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in)
405       : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
406                   //(via basic_ios::init() call in base_t's constructor) without the risk of a
407                   //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
408       , vectorbuf_t(mode | std::ios_base::in)
409    {  this->base_t::rdbuf(&get_buf()); }
410 
411    //!Constructor. Throws if vector_type(const VectorParameter &param)
412    //!throws.
413    template<class VectorParameter>
basic_ivectorstream(const VectorParameter & param,std::ios_base::openmode mode=std::ios_base::in)414    basic_ivectorstream(const VectorParameter &param,
415                        std::ios_base::openmode mode = std::ios_base::in)
416       : vectorbuf_t(param, mode | std::ios_base::in)
417          //basic_ios_t() is constructed uninitialized as virtual base
418          //and initialized inside base_t calling basic_ios::init()
419       , base_t(&get_buf())
420    {}
421 
422    public:
423    //!Returns the address of the stored
424    //!stream buffer.
rdbuf() const425    basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
426    { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
427 
428    //!Swaps the underlying vector with the passed vector.
429    //!This function resets the read position in the stream.
430    //!Does not throw.
swap_vector(vector_type & vect)431    void swap_vector(vector_type &vect)
432    {  get_buf().swap_vector(vect);   }
433 
434    //!Returns a const reference to the internal vector.
435    //!Does not throw.
vector() const436    const vector_type &vector() const
437    {  return get_buf().vector();   }
438 
439    //!Calls reserve() method of the internal vector.
440    //!Resets the stream to the first position.
441    //!Throws if the internals vector's reserve throws.
reserve(typename vector_type::size_type size)442    void reserve(typename vector_type::size_type size)
443    {  get_buf().reserve(size);   }
444 
445    //!Calls clear() method of the internal vector.
446    //!Resets the stream to the first position.
clear()447    void clear()
448    {  get_buf().clear();   }
449 };
450 
451 //!A basic_ostream class that holds a character vector specified by CharVector
452 //!template parameter as its formatting buffer. The vector must have
453 //!contiguous storage, like std::vector, boost::interprocess::vector or
454 //!boost::interprocess::basic_string
455 template <class CharVector, class CharTraits>
456 class basic_ovectorstream
457    : public std::basic_ostream<typename CharVector::value_type, CharTraits>
458    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
459    , private basic_vectorbuf<CharVector, CharTraits>
460    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
461 {
462    public:
463    typedef CharVector                                                   vector_type;
464    typedef typename std::basic_ios
465       <typename CharVector::value_type, CharTraits>::char_type          char_type;
466    typedef typename std::basic_ios<char_type, CharTraits>::int_type     int_type;
467    typedef typename std::basic_ios<char_type, CharTraits>::pos_type     pos_type;
468    typedef typename std::basic_ios<char_type, CharTraits>::off_type     off_type;
469    typedef typename std::basic_ios<char_type, CharTraits>::traits_type  traits_type;
470 
471    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
472    private:
473    typedef basic_vectorbuf<CharVector, CharTraits>    vectorbuf_t;
474    typedef std::basic_ios<char_type, CharTraits>      basic_ios_t;
475    typedef std::basic_ostream<char_type, CharTraits>  base_t;
476 
get_buf()477    vectorbuf_t &       get_buf()      {  return *this;  }
get_buf() const478    const vectorbuf_t & get_buf()const {  return *this;  }
479    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
480 
481    public:
482    //!Constructor. Throws if vector_type default
483    //!constructor throws.
basic_ovectorstream(std::ios_base::openmode mode=std::ios_base::out)484    basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out)
485       : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
486                   //(via basic_ios::init() call in base_t's constructor) without the risk of a
487                   //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
488       , vectorbuf_t(mode | std::ios_base::out)
489    {  this->base_t::rdbuf(&get_buf()); }
490 
491    //!Constructor. Throws if vector_type(const VectorParameter &param)
492    //!throws.
493    template<class VectorParameter>
basic_ovectorstream(const VectorParameter & param,std::ios_base::openmode mode=std::ios_base::out)494    basic_ovectorstream(const VectorParameter &param,
495                         std::ios_base::openmode mode = std::ios_base::out)
496       : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
497                   //(via basic_ios::init() call in base_t's constructor) without the risk of a
498                   //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
499       , vectorbuf_t(param, mode | std::ios_base::out)
500    {  this->base_t::rdbuf(&get_buf()); }
501 
502    public:
503    //!Returns the address of the stored
504    //!stream buffer.
rdbuf() const505    basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
506    { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
507 
508    //!Swaps the underlying vector with the passed vector.
509    //!This function resets the write position in the stream.
510    //!Does not throw.
swap_vector(vector_type & vect)511    void swap_vector(vector_type &vect)
512    {  get_buf().swap_vector(vect);   }
513 
514    //!Returns a const reference to the internal vector.
515    //!Does not throw.
vector() const516    const vector_type &vector() const
517    {  return get_buf().vector();   }
518 
519    //!Calls reserve() method of the internal vector.
520    //!Resets the stream to the first position.
521    //!Throws if the internals vector's reserve throws.
reserve(typename vector_type::size_type size)522    void reserve(typename vector_type::size_type size)
523    {  get_buf().reserve(size);   }
524 };
525 
526 //!A basic_iostream class that holds a character vector specified by CharVector
527 //!template parameter as its formatting buffer. The vector must have
528 //!contiguous storage, like std::vector, boost::interprocess::vector or
529 //!boost::interprocess::basic_string
530 template <class CharVector, class CharTraits>
531 class basic_vectorstream
532    : public std::basic_iostream<typename CharVector::value_type, CharTraits>
533    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
534    , private basic_vectorbuf<CharVector, CharTraits>
535    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
536 {
537    public:
538    typedef CharVector                                                   vector_type;
539    typedef typename std::basic_ios
540       <typename CharVector::value_type, CharTraits>::char_type          char_type;
541    typedef typename std::basic_ios<char_type, CharTraits>::int_type     int_type;
542    typedef typename std::basic_ios<char_type, CharTraits>::pos_type     pos_type;
543    typedef typename std::basic_ios<char_type, CharTraits>::off_type     off_type;
544    typedef typename std::basic_ios<char_type, CharTraits>::traits_type  traits_type;
545 
546    #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED)
547    private:
548    typedef basic_vectorbuf<CharVector, CharTraits>    vectorbuf_t;
549    typedef std::basic_ios<char_type, CharTraits>      basic_ios_t;
550    typedef std::basic_iostream<char_type, CharTraits> base_t;
551 
get_buf()552    vectorbuf_t &       get_buf()      {  return *this;  }
get_buf() const553    const vectorbuf_t & get_buf() const{  return *this;  }
554    #endif   //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
555 
556    public:
557    //!Constructor. Throws if vector_type default
558    //!constructor throws.
basic_vectorstream(std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)559    basic_vectorstream(std::ios_base::openmode mode
560                       = std::ios_base::in | std::ios_base::out)
561       : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
562                   //(via basic_ios::init() call in base_t's constructor) without the risk of a
563                   //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
564       , vectorbuf_t(mode)
565    {  this->base_t::rdbuf(&get_buf()); }
566 
567    //!Constructor. Throws if vector_type(const VectorParameter &param)
568    //!throws.
569    template<class VectorParameter>
basic_vectorstream(const VectorParameter & param,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)570    basic_vectorstream(const VectorParameter &param, std::ios_base::openmode mode
571                       = std::ios_base::in | std::ios_base::out)
572       : base_t(0) //Initializes first the base class to safely init the virtual basic_ios base
573                   //(via basic_ios::init() call in base_t's constructor) without the risk of a
574                   //previous throwing vectorbuf constructor. Set the streambuf after risk has gone.
575       , vectorbuf_t(param, mode)
576    {  this->base_t::rdbuf(&get_buf()); }
577 
578    public:
579    //Returns the address of the stored stream buffer.
rdbuf() const580    basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
581    { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&get_buf()); }
582 
583    //!Swaps the underlying vector with the passed vector.
584    //!This function resets the read/write position in the stream.
585    //!Does not throw.
swap_vector(vector_type & vect)586    void swap_vector(vector_type &vect)
587    {  get_buf().swap_vector(vect);   }
588 
589    //!Returns a const reference to the internal vector.
590    //!Does not throw.
vector() const591    const vector_type &vector() const
592    {  return get_buf().vector();   }
593 
594    //!Calls reserve() method of the internal vector.
595    //!Resets the stream to the first position.
596    //!Throws if the internals vector's reserve throws.
reserve(typename vector_type::size_type size)597    void reserve(typename vector_type::size_type size)
598    {  get_buf().reserve(size);   }
599 
600    //!Calls clear() method of the internal vector.
601    //!Resets the stream to the first position.
clear()602    void clear()
603    {  get_buf().clear();   }
604 };
605 
606 //Some typedefs to simplify usage
607 //!
608 //!typedef basic_vectorbuf<std::vector<char> >        vectorbuf;
609 //!typedef basic_vectorstream<std::vector<char> >     vectorstream;
610 //!typedef basic_ivectorstream<std::vector<char> >    ivectorstream;
611 //!typedef basic_ovectorstream<std::vector<char> >    ovectorstream;
612 //!
613 //!typedef basic_vectorbuf<std::vector<wchar_t> >     wvectorbuf;
614 //!typedef basic_vectorstream<std::vector<wchar_t> >  wvectorstream;
615 //!typedef basic_ivectorstream<std::vector<wchar_t> > wivectorstream;
616 //!typedef basic_ovectorstream<std::vector<wchar_t> > wovectorstream;
617 
618 }} //namespace boost {  namespace interprocess {
619 
620 #include <boost/interprocess/detail/config_end.hpp>
621 
622 #endif /* BOOST_INTERPROCESS_VECTORSTREAM_HPP */
623