123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 |
- //////////////////////////////////////////////////////////////////////////////
- //
- // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
- // Software License, Version 1.0. (See accompanying file
- // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- // See http://www.boost.org/libs/interprocess for documentation.
- //
- //////////////////////////////////////////////////////////////////////////////
- //
- // This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012.
- // Changed internal SGI string to a generic, templatized vector. Added efficient
- // internal buffer get/set/swap functions, so that we can obtain/establish the
- // internal buffer without any reallocation or copy. Kill those temporaries!
- ///////////////////////////////////////////////////////////////////////////////
- /*
- * Copyright (c) 1998
- * Silicon Graphics Computer Systems, Inc.
- *
- * Permission to use, copy, modify, distribute and sell this software
- * and its documentation for any purpose is hereby granted without fee,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation. Silicon Graphics makes no
- * representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied warranty.
- */
- //!\file
- //!This file defines basic_vectorbuf, basic_ivectorstream,
- //!basic_ovectorstream, and basic_vectorstreamclasses. These classes
- //!represent streamsbufs and streams whose sources or destinations are
- //!STL-like vectors that can be swapped with external vectors to avoid
- //!unnecessary allocations/copies.
- #ifndef BOOST_INTERPROCESS_VECTORSTREAM_HPP
- #define BOOST_INTERPROCESS_VECTORSTREAM_HPP
- #include <boost/interprocess/detail/config_begin.hpp>
- #include <boost/interprocess/detail/workaround.hpp>
- #include <iosfwd>
- #include <ios>
- #include <istream>
- #include <ostream>
- #include <string> // char traits
- #include <cstddef> // ptrdiff_t
- #include <boost/interprocess/interprocess_fwd.hpp>
- #include <boost/assert.hpp>
- namespace boost { namespace interprocess {
- //!A streambuf class that controls the transmission of elements to and from
- //!a basic_ivectorstream, basic_ovectorstream or basic_vectorstream.
- //!It holds a character vector specified by CharVector template parameter
- //!as its formatting buffer. The vector must have contiguous storage, like
- //!std::vector, boost::interprocess::vector or boost::interprocess::basic_string
- template <class CharVector, class CharTraits>
- class basic_vectorbuf
- : public std::basic_streambuf<typename CharVector::value_type, CharTraits>
- {
- public:
- typedef CharVector vector_type;
- typedef typename CharVector::value_type char_type;
- typedef typename CharTraits::int_type int_type;
- typedef typename CharTraits::pos_type pos_type;
- typedef typename CharTraits::off_type off_type;
- typedef CharTraits traits_type;
- /// @cond
- private:
- typedef std::basic_streambuf<char_type, traits_type> base_t;
- basic_vectorbuf(const basic_vectorbuf&);
- basic_vectorbuf & operator =(const basic_vectorbuf&);
- /// @endcond
- public:
- //!Constructor. Throws if vector_type default
- //!constructor throws.
- explicit basic_vectorbuf(std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
- : base_t(), m_mode(mode)
- { this->initialize_pointers(); }
- //!Constructor. Throws if
- //!vector_type(const VectorParameter ¶m) throws.
- template<class VectorParameter>
- explicit basic_vectorbuf(const VectorParameter ¶m,
- std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
- : base_t(), m_mode(mode), m_vect(param)
- { this->initialize_pointers(); }
- virtual ~basic_vectorbuf(){}
- public:
- //!Swaps the underlying vector with the passed vector.
- //!This function resets the read/write position in the stream.
- //!Does not throw.
- void swap_vector(vector_type &vect)
- {
- if (this->m_mode & std::ios_base::out){
- //Update high water if necessary
- //And resize vector to remove extra size
- if (mp_high_water < base_t::pptr()){
- //Restore the vector's size if necessary
- mp_high_water = base_t::pptr();
- }
- //This does not reallocate
- m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0));
- }
- //Now swap vector
- m_vect.swap(vect);
- this->initialize_pointers();
- }
- //!Returns a const reference to the internal vector.
- //!Does not throw.
- const vector_type &vector() const
- {
- if (this->m_mode & std::ios_base::out){
- if (mp_high_water < base_t::pptr()){
- //Restore the vector's size if necessary
- mp_high_water = base_t::pptr();
- }
- //This shouldn't reallocate
- typedef typename vector_type::size_type size_type;
- char_type *old_ptr = base_t::pbase();
- size_type high_pos = size_type(mp_high_water-old_ptr);
- if(m_vect.size() > high_pos){
- m_vect.resize(high_pos);
- //But we must update end write pointer because vector size is now shorter
- int old_pos = base_t::pptr() - base_t::pbase();
- const_cast<basic_vectorbuf*>(this)->base_t::setp(old_ptr, old_ptr + high_pos);
- const_cast<basic_vectorbuf*>(this)->base_t::pbump(old_pos);
- }
- }
- return m_vect;
- }
- //!Preallocates memory from the internal vector.
- //!Resets the stream to the first position.
- //!Throws if the internals vector's memory allocation throws.
- void reserve(typename vector_type::size_type size)
- {
- if (this->m_mode & std::ios_base::out && size > m_vect.size()){
- typename vector_type::difference_type write_pos = base_t::pptr() - base_t::pbase();
- typename vector_type::difference_type read_pos = base_t::gptr() - base_t::eback();
- //Now update pointer data
- m_vect.reserve(size);
- this->initialize_pointers();
- base_t::pbump((int)write_pos);
- if(this->m_mode & std::ios_base::in){
- base_t::gbump((int)read_pos);
- }
- }
- }
- //!Calls clear() method of the internal vector.
- //!Resets the stream to the first position.
- void clear()
- { m_vect.clear(); this->initialize_pointers(); }
- /// @cond
- private:
- //Maximizes high watermark to the initial vector size,
- //initializes read and write iostream buffers to the capacity
- //and resets stream positions
- void initialize_pointers()
- {
- // The initial read position is the beginning of the vector.
- if(!(m_mode & std::ios_base::out)){
- if(m_vect.empty()){
- this->setg(0, 0, 0);
- }
- else{
- this->setg(&m_vect[0], &m_vect[0], &m_vect[0] + m_vect.size());
- }
- }
- // The initial write position is the beginning of the vector.
- if(m_mode & std::ios_base::out){
- //First get real size
- int real_size = (int)m_vect.size();
- //Then maximize size for high watermarking
- m_vect.resize(m_vect.capacity());
- BOOST_ASSERT(m_vect.size() == m_vect.capacity());
- //Set high watermarking with the expanded size
- mp_high_water = m_vect.size() ? (&m_vect[0] + real_size) : 0;
- //Now set formatting pointers
- if(m_vect.empty()){
- this->setp(0, 0);
- if(m_mode & std::ios_base::in)
- this->setg(0, 0, 0);
- }
- else{
- char_type *p = &m_vect[0];
- this->setp(p, p + m_vect.size());
- if(m_mode & std::ios_base::in)
- this->setg(p, p, p + real_size);
- }
- if (m_mode & (std::ios_base::app | std::ios_base::ate)){
- base_t::pbump((int)real_size);
- }
- }
- }
- protected:
- virtual int_type underflow()
- {
- if (base_t::gptr() == 0)
- return CharTraits::eof();
- if(m_mode & std::ios_base::out){
- if (mp_high_water < base_t::pptr())
- mp_high_water = base_t::pptr();
- if (base_t::egptr() < mp_high_water)
- base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water);
- }
- if (base_t::gptr() < base_t::egptr())
- return CharTraits::to_int_type(*base_t::gptr());
- return CharTraits::eof();
- }
- virtual int_type pbackfail(int_type c = CharTraits::eof())
- {
- if(this->gptr() != this->eback()) {
- if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
- if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) {
- this->gbump(-1);
- return c;
- }
- else if(m_mode & std::ios_base::out) {
- this->gbump(-1);
- *this->gptr() = c;
- return c;
- }
- else
- return CharTraits::eof();
- }
- else {
- this->gbump(-1);
- return CharTraits::not_eof(c);
- }
- }
- else
- return CharTraits::eof();
- }
- virtual int_type overflow(int_type c = CharTraits::eof())
- {
- if(m_mode & std::ios_base::out) {
- if(!CharTraits::eq_int_type(c, CharTraits::eof())) {
- typedef typename vector_type::difference_type dif_t;
- //The new output position is the previous one plus one
- //because 'overflow' requires putting 'c' on the buffer
- dif_t new_outpos = base_t::pptr() - base_t::pbase() + 1;
- //Adjust high water if necessary
- dif_t hipos = mp_high_water - base_t::pbase();
- if (hipos < new_outpos)
- hipos = new_outpos;
- //Insert the new data
- m_vect.push_back(CharTraits::to_char_type(c));
- m_vect.resize(m_vect.capacity());
- BOOST_ASSERT(m_vect.size() == m_vect.capacity());
- char_type* p = const_cast<char_type*>(&m_vect[0]);
- //A reallocation might have happened, update pointers
- base_t::setp(p, p + (dif_t)m_vect.size());
- mp_high_water = p + hipos;
- if (m_mode & std::ios_base::in)
- base_t::setg(p, p + (base_t::gptr() - base_t::eback()), mp_high_water);
- //Update write position to the old position + 1
- base_t::pbump((int)new_outpos);
- return c;
- }
- else // c is EOF, so we don't have to do anything
- return CharTraits::not_eof(c);
- }
- else // Overflow always fails if it's read-only.
- return CharTraits::eof();
- }
- virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir,
- std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
- {
- //Get seek mode
- bool in(0 != (mode & std::ios_base::in)), out(0 != (mode & std::ios_base::out));
- //Test for logic errors
- if(!in & !out)
- return pos_type(off_type(-1));
- else if((in && out) && (dir == std::ios_base::cur))
- return pos_type(off_type(-1));
- else if((in && (!(m_mode & std::ios_base::in) || this->gptr() == 0)) ||
- (out && (!(m_mode & std::ios_base::out) || this->pptr() == 0)))
- return pos_type(off_type(-1));
- off_type newoff;
- //Just calculate the end of the stream. If the stream is read-only
- //the limit is the size of the vector. Otherwise, the high water mark
- //will mark the real size.
- off_type limit;
- if(m_mode & std::ios_base::out){
- //Update high water marking because pptr() is going to change and it might
- //have been updated since last overflow()
- if(mp_high_water < base_t::pptr())
- mp_high_water = base_t::pptr();
- //Update read limits in case high water mark was changed
- if(m_mode & std::ios_base::in){
- if (base_t::egptr() < mp_high_water)
- base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water);
- }
- limit = static_cast<off_type>(mp_high_water - base_t::pbase());
- }
- else{
- limit = static_cast<off_type>(m_vect.size());
- }
- switch(dir) {
- case std::ios_base::beg:
- newoff = 0;
- break;
- case std::ios_base::end:
- newoff = limit;
- break;
- case std::ios_base::cur:
- newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback())
- : static_cast<std::streamoff>(this->pptr() - this->pbase());
- break;
- default:
- return pos_type(off_type(-1));
- }
- newoff += off;
- if (newoff < 0 || newoff > limit)
- return pos_type(-1);
- if (m_mode & std::ios_base::app && mode & std::ios_base::out && newoff != limit)
- return pos_type(-1);
- //This can reassign pointers
- //if(m_vect.size() != m_vect.capacity())
- //this->initialize_pointers();
- if (in)
- base_t::setg(base_t::eback(), base_t::eback() + newoff, base_t::egptr());
- if (out){
- base_t::setp(base_t::pbase(), base_t::epptr());
- base_t::pbump(newoff);
- }
- return pos_type(newoff);
- }
- virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
- { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); }
- private:
- std::ios_base::openmode m_mode;
- mutable vector_type m_vect;
- mutable char_type* mp_high_water;
- /// @endcond
- };
- //!A basic_istream class that holds a character vector specified by CharVector
- //!template parameter as its formatting buffer. The vector must have
- //!contiguous storage, like std::vector, boost::interprocess::vector or
- //!boost::interprocess::basic_string
- template <class CharVector, class CharTraits>
- class basic_ivectorstream
- /// @cond
- : private basic_vectorbuf<CharVector, CharTraits>
- /// @endcond
- , public std::basic_istream<typename CharVector::value_type, CharTraits>
- {
- public:
- typedef CharVector vector_type;
- typedef typename std::basic_ios
- <typename CharVector::value_type, CharTraits>::char_type char_type;
- typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
- typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
- typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
- typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
- private:
- typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
- typedef std::basic_istream<char_type, CharTraits> base_t;
- vectorbuf_t & m_buf() { return *this; }
- const vectorbuf_t & m_buf() const{ return *this; }
- /// @endcond
- public:
- //!Constructor. Throws if vector_type default
- //!constructor throws.
- basic_ivectorstream(std::ios_base::openmode mode = std::ios_base::in)
- : vectorbuf_t(mode | std::ios_base::in), base_t(&m_buf())
- {}
- //!Constructor. Throws if vector_type(const VectorParameter ¶m)
- //!throws.
- template<class VectorParameter>
- basic_ivectorstream(const VectorParameter ¶m,
- std::ios_base::openmode mode = std::ios_base::in)
- : vectorbuf_t(param, mode | std::ios_base::in), base_t(&m_buf())
- {}
- ~basic_ivectorstream(){};
- public:
- //!Returns the address of the stored
- //!stream buffer.
- basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
- { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); }
- //!Swaps the underlying vector with the passed vector.
- //!This function resets the read position in the stream.
- //!Does not throw.
- void swap_vector(vector_type &vect)
- { m_buf().swap_vector(vect); }
- //!Returns a const reference to the internal vector.
- //!Does not throw.
- const vector_type &vector() const
- { return m_buf().vector(); }
- //!Calls reserve() method of the internal vector.
- //!Resets the stream to the first position.
- //!Throws if the internals vector's reserve throws.
- void reserve(typename vector_type::size_type size)
- { m_buf().reserve(size); }
- //!Calls clear() method of the internal vector.
- //!Resets the stream to the first position.
- void clear()
- { m_buf().clear(); }
- };
- //!A basic_ostream class that holds a character vector specified by CharVector
- //!template parameter as its formatting buffer. The vector must have
- //!contiguous storage, like std::vector, boost::interprocess::vector or
- //!boost::interprocess::basic_string
- template <class CharVector, class CharTraits>
- class basic_ovectorstream
- /// @cond
- : private basic_vectorbuf<CharVector, CharTraits>
- /// @endcond
- , public std::basic_ostream<typename CharVector::value_type, CharTraits>
- {
- public:
- typedef CharVector vector_type;
- typedef typename std::basic_ios
- <typename CharVector::value_type, CharTraits>::char_type char_type;
- typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
- typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
- typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
- typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
- private:
- typedef basic_vectorbuf<CharVector, CharTraits> vectorbuf_t;
- typedef std::basic_ostream<char_type, CharTraits> base_t;
- vectorbuf_t & m_buf() { return *this; }
- const vectorbuf_t & m_buf()const { return *this; }
- /// @endcond
- public:
- //!Constructor. Throws if vector_type default
- //!constructor throws.
- basic_ovectorstream(std::ios_base::openmode mode = std::ios_base::out)
- : vectorbuf_t(mode | std::ios_base::out), base_t(&m_buf())
- {}
- //!Constructor. Throws if vector_type(const VectorParameter ¶m)
- //!throws.
- template<class VectorParameter>
- basic_ovectorstream(const VectorParameter ¶m,
- std::ios_base::openmode mode = std::ios_base::out)
- : vectorbuf_t(param, mode | std::ios_base::out), base_t(&m_buf())
- {}
- ~basic_ovectorstream(){}
- public:
- //!Returns the address of the stored
- //!stream buffer.
- basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
- { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf()); }
- //!Swaps the underlying vector with the passed vector.
- //!This function resets the write position in the stream.
- //!Does not throw.
- void swap_vector(vector_type &vect)
- { m_buf().swap_vector(vect); }
- //!Returns a const reference to the internal vector.
- //!Does not throw.
- const vector_type &vector() const
- { return m_buf().vector(); }
- //!Calls reserve() method of the internal vector.
- //!Resets the stream to the first position.
- //!Throws if the internals vector's reserve throws.
- void reserve(typename vector_type::size_type size)
- { m_buf().reserve(size); }
- };
- //!A basic_iostream class that holds a character vector specified by CharVector
- //!template parameter as its formatting buffer. The vector must have
- //!contiguous storage, like std::vector, boost::interprocess::vector or
- //!boost::interprocess::basic_string
- template <class CharVector, class CharTraits>
- class basic_vectorstream
- : public std::basic_iostream<typename CharVector::value_type, CharTraits>
- {
- public:
- typedef CharVector vector_type;
- typedef typename std::basic_ios
- <typename CharVector::value_type, CharTraits>::char_type char_type;
- typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
- typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
- typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
- typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
- /// @cond
- private:
- typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
- typedef std::basic_iostream<char_type, CharTraits> base_t;
- /// @endcond
- public:
- //!Constructor. Throws if vector_type default
- //!constructor throws.
- basic_vectorstream(std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
- : basic_ios_t(), base_t(0), m_buf(mode)
- { basic_ios_t::init(&m_buf); }
- //!Constructor. Throws if vector_type(const VectorParameter ¶m)
- //!throws.
- template<class VectorParameter>
- basic_vectorstream(const VectorParameter ¶m, std::ios_base::openmode mode
- = std::ios_base::in | std::ios_base::out)
- : basic_ios_t(), base_t(0), m_buf(param, mode)
- { basic_ios_t::init(&m_buf); }
- ~basic_vectorstream(){}
- public:
- //Returns the address of the stored stream buffer.
- basic_vectorbuf<CharVector, CharTraits>* rdbuf() const
- { return const_cast<basic_vectorbuf<CharVector, CharTraits>*>(&m_buf); }
- //!Swaps the underlying vector with the passed vector.
- //!This function resets the read/write position in the stream.
- //!Does not throw.
- void swap_vector(vector_type &vect)
- { m_buf.swap_vector(vect); }
- //!Returns a const reference to the internal vector.
- //!Does not throw.
- const vector_type &vector() const
- { return m_buf.vector(); }
- //!Calls reserve() method of the internal vector.
- //!Resets the stream to the first position.
- //!Throws if the internals vector's reserve throws.
- void reserve(typename vector_type::size_type size)
- { m_buf.reserve(size); }
- //!Calls clear() method of the internal vector.
- //!Resets the stream to the first position.
- void clear()
- { m_buf.clear(); }
- /// @cond
- private:
- basic_vectorbuf<CharVector, CharTraits> m_buf;
- /// @endcond
- };
- //Some typedefs to simplify usage
- //!
- //!typedef basic_vectorbuf<std::vector<char> > vectorbuf;
- //!typedef basic_vectorstream<std::vector<char> > vectorstream;
- //!typedef basic_ivectorstream<std::vector<char> > ivectorstream;
- //!typedef basic_ovectorstream<std::vector<char> > ovectorstream;
- //!
- //!typedef basic_vectorbuf<std::vector<wchar_t> > wvectorbuf;
- //!typedef basic_vectorstream<std::vector<wchar_t> > wvectorstream;
- //!typedef basic_ivectorstream<std::vector<wchar_t> > wivectorstream;
- //!typedef basic_ovectorstream<std::vector<wchar_t> > wovectorstream;
- }} //namespace boost { namespace interprocess {
- #include <boost/interprocess/detail/config_end.hpp>
- #endif /* BOOST_INTERPROCESS_VECTORSTREAM_HPP */
|