vectorstream.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 594 行 · 第 1/2 页

HPP
594
字号
////////////////////////////////////////////////////////////////////////////////// (C) Copyright Ion Gaztanaga 2005-2008. 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.// 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 <cassert>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_stringtemplate <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 &param) throws.   template<class VectorParameter>   explicit basic_vectorbuf(const VectorParameter &param,                            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();         }         m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0));         //Now swap vector         m_vect.swap(vect);         //If the stream is writable put the high water mark         //and maximize the size.         typename vector_type::size_type old_size = m_vect.size();         m_vect.resize(m_vect.capacity());         this->initialize_pointers();         mp_high_water = old_size ? &m_vect[0] + old_size : 0;      }      else{         //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();         }         m_vect.resize(mp_high_water - (m_vect.size() ? &m_vect[0] : 0));         const_cast<basic_vectorbuf * const>(this)->initialize_pointers();      }      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)    {      m_vect.reserve(size);      //Now update pointer data      typename vector_type::size_type old_size = m_vect.size();      m_vect.resize(m_vect.capacity());      this->initialize_pointers();      mp_high_water = old_size ? &m_vect[0] + old_size : 0;   }   //!Calls clear() method of the internal vector.   //!Resets the stream to the first position.   void clear()    {  m_vect.clear();   this->initialize_pointers();   }   /// @cond   private:   void initialize_pointers()   {      // The initial read position is the beginning of the vector.      if(m_mode & std::ios_base::in){         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){         if(m_vect.empty()){            this->setp(0, 0);         }         else{            this->setp(&m_vect[0], &m_vect[0] + m_vect.size());         }         if (m_mode & (std::ios_base::app | std::ios_base::ate))            base_t::pbump((int)m_vect.size());      }      mp_high_water = m_vect.empty() ? 0 : (&m_vect[0] + m_vect.size());   }   protected:   virtual int_type underflow()   {      if (base_t::gptr() == 0)         return CharTraits::eof();      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())) {//            if(!(m_mode & std::ios_base::in)) {//               if(this->pptr() < this->epptr()) {//                  *this->pptr() = CharTraits::to_char_type(c);//                           this->pbump(1);//                  if (mp_high_water < base_t::pptr())//                     mp_high_water = base_t::pptr();//                  if ((m_mode & std::ios_base::in) && base_t::egptr() < mp_high_water)//                     base_t::setg(base_t::eback(), base_t::gptr(), mp_high_water);//                  return c;//               }//               else//                  return CharTraits::eof();//            }//            else {//               try{                  typedef typename vector_type::difference_type dif_t;                  dif_t inpos  = base_t::gptr() - base_t::eback();                  //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());                  char_type* p = const_cast<char_type*>(&m_vect[0]);                  //A reallocation has happened, update pointers                  if (m_mode & std::ios_base::in)                     base_t::setg(p, p + inpos, p + hipos);                  base_t::setp(p, p + (dif_t)m_vect.size());                  //Update write position to the old position + 1                  base_t::pbump((int)new_outpos);                  //Update high water pointer, since the buffer has been reallocated                  mp_high_water = base_t::pbase() + hipos;                  return c;//               }//               catch(...){//                  return CharTraits::eof();//               }//            }         }         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)   {      bool in = false, out = false;               const std::ios_base::openmode inout =          std::ios_base::in | std::ios_base::out;      if((mode & inout) == inout) {         if(dir == std::ios_base::beg || dir == std::ios_base::end)            in = out = true;      }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?