Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // See http://www.boost.org/libs/interprocess for documentation. Chris@16: // Chris@16: ////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // This file comes from SGI's sstream file. Modified by Ion Gaztanaga 2005-2012. Chris@16: // Changed internal SGI string to a buffer. Added efficient Chris@16: // internal buffer get/set/swap functions, so that we can obtain/establish the Chris@16: // internal buffer without any reallocation or copy. Kill those temporaries! Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /* Chris@16: * Copyright (c) 1998 Chris@16: * Silicon Graphics Computer Systems, Inc. Chris@16: * Chris@16: * Permission to use, copy, modify, distribute and sell this software Chris@16: * and its documentation for any purpose is hereby granted without fee, Chris@16: * provided that the above copyright notice appear in all copies and Chris@16: * that both that copyright notice and this permission notice appear Chris@16: * in supporting documentation. Silicon Graphics makes no Chris@16: * representations about the suitability of this software for any Chris@16: * purpose. It is provided "as is" without express or implied warranty. Chris@16: */ Chris@16: Chris@16: //!\file Chris@16: //!This file defines basic_bufferbuf, basic_ibufferstream, Chris@16: //!basic_obufferstream, and basic_bufferstream classes. These classes Chris@16: //!represent streamsbufs and streams whose sources or destinations Chris@16: //!are fixed size character buffers. Chris@16: Chris@16: #ifndef BOOST_INTERPROCESS_BUFFERSTREAM_HPP Chris@16: #define BOOST_INTERPROCESS_BUFFERSTREAM_HPP Chris@16: Chris@101: #ifndef BOOST_CONFIG_HPP Chris@101: # include Chris@101: #endif Chris@101: # Chris@101: #if defined(BOOST_HAS_PRAGMA_ONCE) Chris@101: # pragma once Chris@101: #endif Chris@101: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include // char traits Chris@16: #include // ptrdiff_t Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace interprocess { Chris@16: Chris@16: //!A streambuf class that controls the transmission of elements to and from Chris@16: //!a basic_xbufferstream. The elements are transmitted from a to a fixed Chris@16: //!size buffer Chris@16: template Chris@16: class basic_bufferbuf Chris@16: : public std::basic_streambuf Chris@16: { Chris@16: public: Chris@16: typedef CharT char_type; Chris@16: typedef typename CharTraits::int_type int_type; Chris@16: typedef typename CharTraits::pos_type pos_type; Chris@16: typedef typename CharTraits::off_type off_type; Chris@16: typedef CharTraits traits_type; Chris@16: typedef std::basic_streambuf base_t; Chris@16: Chris@16: public: Chris@16: //!Constructor. Chris@16: //!Does not throw. Chris@16: explicit basic_bufferbuf(std::ios_base::openmode mode Chris@16: = std::ios_base::in | std::ios_base::out) Chris@16: : base_t(), m_mode(mode), m_buffer(0), m_length(0) Chris@16: {} Chris@16: Chris@16: //!Constructor. Assigns formatting buffer. Chris@16: //!Does not throw. Chris@16: explicit basic_bufferbuf(CharT *buf, std::size_t length, Chris@16: std::ios_base::openmode mode Chris@16: = std::ios_base::in | std::ios_base::out) Chris@16: : base_t(), m_mode(mode), m_buffer(buf), m_length(length) Chris@16: { this->set_pointers(); } Chris@16: Chris@16: virtual ~basic_bufferbuf(){} Chris@16: Chris@16: public: Chris@16: //!Returns the pointer and size of the internal buffer. Chris@16: //!Does not throw. Chris@16: std::pair buffer() const Chris@16: { return std::pair(m_buffer, m_length); } Chris@16: Chris@16: //!Sets the underlying buffer to a new value Chris@16: //!Does not throw. Chris@16: void buffer(CharT *buf, std::size_t length) Chris@16: { m_buffer = buf; m_length = length; this->set_pointers(); } Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private: Chris@16: void set_pointers() Chris@16: { Chris@16: // The initial read position is the beginning of the buffer. Chris@16: if(m_mode & std::ios_base::in) Chris@16: this->setg(m_buffer, m_buffer, m_buffer + m_length); Chris@16: Chris@16: // The initial write position is the beginning of the buffer. Chris@16: if(m_mode & std::ios_base::out) Chris@16: this->setp(m_buffer, m_buffer + m_length); Chris@16: } Chris@16: Chris@16: protected: Chris@16: virtual int_type underflow() Chris@16: { Chris@16: // Precondition: gptr() >= egptr(). Returns a character, if available. Chris@16: return this->gptr() != this->egptr() ? Chris@16: CharTraits::to_int_type(*this->gptr()) : CharTraits::eof(); Chris@16: } Chris@16: Chris@16: virtual int_type pbackfail(int_type c = CharTraits::eof()) Chris@16: { Chris@16: if(this->gptr() != this->eback()) { Chris@16: if(!CharTraits::eq_int_type(c, CharTraits::eof())) { Chris@16: if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) { Chris@16: this->gbump(-1); Chris@16: return c; Chris@16: } Chris@16: else if(m_mode & std::ios_base::out) { Chris@16: this->gbump(-1); Chris@16: *this->gptr() = c; Chris@16: return c; Chris@16: } Chris@16: else Chris@16: return CharTraits::eof(); Chris@16: } Chris@16: else { Chris@16: this->gbump(-1); Chris@16: return CharTraits::not_eof(c); Chris@16: } Chris@16: } Chris@16: else Chris@16: return CharTraits::eof(); Chris@16: } Chris@16: Chris@16: virtual int_type overflow(int_type c = CharTraits::eof()) Chris@16: { Chris@16: if(m_mode & std::ios_base::out) { Chris@16: if(!CharTraits::eq_int_type(c, CharTraits::eof())) { Chris@16: // if(!(m_mode & std::ios_base::in)) { Chris@16: // if(this->pptr() != this->epptr()) { Chris@16: // *this->pptr() = CharTraits::to_char_type(c); Chris@16: // this->pbump(1); Chris@16: // return c; Chris@16: // } Chris@16: // else Chris@16: // return CharTraits::eof(); Chris@16: // } Chris@16: // else { Chris@16: if(this->pptr() == this->epptr()) { Chris@16: //We can't append to a static buffer Chris@16: return CharTraits::eof(); Chris@16: } Chris@16: else { Chris@16: *this->pptr() = CharTraits::to_char_type(c); Chris@16: this->pbump(1); Chris@16: return c; Chris@16: } Chris@16: // } Chris@16: } Chris@16: else // c is EOF, so we don't have to do anything Chris@16: return CharTraits::not_eof(c); Chris@16: } Chris@16: else // Overflow always fails if it's read-only. Chris@16: return CharTraits::eof(); Chris@16: } Chris@16: Chris@16: virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, Chris@16: std::ios_base::openmode mode Chris@16: = std::ios_base::in | std::ios_base::out) Chris@16: { Chris@16: bool in = false; Chris@16: bool out = false; Chris@16: Chris@16: const std::ios_base::openmode inout = Chris@16: std::ios_base::in | std::ios_base::out; Chris@16: Chris@16: if((mode & inout) == inout) { Chris@16: if(dir == std::ios_base::beg || dir == std::ios_base::end) Chris@16: in = out = true; Chris@16: } Chris@16: else if(mode & std::ios_base::in) Chris@16: in = true; Chris@16: else if(mode & std::ios_base::out) Chris@16: out = true; Chris@16: Chris@16: if(!in && !out) Chris@16: return pos_type(off_type(-1)); Chris@16: else if((in && (!(m_mode & std::ios_base::in) || this->gptr() == 0)) || Chris@16: (out && (!(m_mode & std::ios_base::out) || this->pptr() == 0))) Chris@16: return pos_type(off_type(-1)); Chris@16: Chris@16: std::streamoff newoff; Chris@16: switch(dir) { Chris@16: case std::ios_base::beg: Chris@16: newoff = 0; Chris@16: break; Chris@16: case std::ios_base::end: Chris@16: newoff = static_cast(m_length); Chris@16: break; Chris@16: case std::ios_base::cur: Chris@16: newoff = in ? static_cast(this->gptr() - this->eback()) Chris@16: : static_cast(this->pptr() - this->pbase()); Chris@16: break; Chris@16: default: Chris@16: return pos_type(off_type(-1)); Chris@16: } Chris@16: Chris@16: off += newoff; Chris@16: Chris@16: if(in) { Chris@16: std::ptrdiff_t n = this->egptr() - this->eback(); Chris@16: Chris@16: if(off < 0 || off > n) Chris@16: return pos_type(off_type(-1)); Chris@16: else Chris@16: this->setg(this->eback(), this->eback() + off, this->eback() + n); Chris@16: } Chris@16: Chris@16: if(out) { Chris@16: std::ptrdiff_t n = this->epptr() - this->pbase(); Chris@16: Chris@16: if(off < 0 || off > n) Chris@16: return pos_type(off_type(-1)); Chris@16: else { Chris@16: this->setp(this->pbase(), this->pbase() + n); Chris@16: this->pbump(off); Chris@16: } Chris@16: } Chris@16: Chris@16: return pos_type(off); Chris@16: } Chris@16: Chris@16: virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode Chris@16: = std::ios_base::in | std::ios_base::out) Chris@16: { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } Chris@16: Chris@16: private: Chris@16: std::ios_base::openmode m_mode; Chris@16: CharT * m_buffer; Chris@16: std::size_t m_length; Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: }; Chris@16: Chris@16: //!A basic_istream class that uses a fixed size character buffer Chris@16: //!as its formatting buffer. Chris@16: template Chris@16: class basic_ibufferstream : Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private basic_bufferbuf, Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: public std::basic_istream Chris@16: { Chris@16: public: // Typedefs Chris@16: typedef typename std::basic_ios Chris@16: ::char_type char_type; Chris@16: typedef typename std::basic_ios::int_type int_type; Chris@16: typedef typename std::basic_ios::pos_type pos_type; Chris@16: typedef typename std::basic_ios::off_type off_type; Chris@16: typedef typename std::basic_ios::traits_type traits_type; Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private: Chris@16: typedef basic_bufferbuf bufferbuf_t; Chris@16: typedef std::basic_ios basic_ios_t; Chris@16: typedef std::basic_istream base_t; Chris@16: bufferbuf_t & get_buf() { return *this; } Chris@16: const bufferbuf_t & get_buf() const{ return *this; } Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: //!Constructor. Chris@16: //!Does not throw. Chris@16: basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in) Chris@16: : //basic_ios_t() is called first (lefting it uninitialized) as it's a Chris@16: //virtual base of basic_istream. The class will be initialized when Chris@16: //basic_istream is constructed calling basic_ios_t::init(). Chris@16: //As bufferbuf_t's constructor does not throw there is no risk of Chris@16: //calling the basic_ios_t's destructor without calling basic_ios_t::init() Chris@16: bufferbuf_t(mode | std::ios_base::in) Chris@16: , base_t(&get_buf()) Chris@16: {} Chris@16: Chris@16: //!Constructor. Assigns formatting buffer. Chris@16: //!Does not throw. Chris@16: basic_ibufferstream(const CharT *buf, std::size_t length, Chris@16: std::ios_base::openmode mode = std::ios_base::in) Chris@16: : //basic_ios_t() is called first (lefting it uninitialized) as it's a Chris@16: //virtual base of basic_istream. The class will be initialized when Chris@16: //basic_istream is constructed calling basic_ios_t::init(). Chris@16: //As bufferbuf_t's constructor does not throw there is no risk of Chris@16: //calling the basic_ios_t's destructor without calling basic_ios_t::init() Chris@16: bufferbuf_t(const_cast(buf), length, mode | std::ios_base::in) Chris@16: , base_t(&get_buf()) Chris@16: {} Chris@16: Chris@16: ~basic_ibufferstream(){}; Chris@16: Chris@16: public: Chris@16: //!Returns the address of the stored Chris@16: //!stream buffer. Chris@16: basic_bufferbuf* rdbuf() const Chris@16: { return const_cast*>(&get_buf()); } Chris@16: Chris@16: //!Returns the pointer and size of the internal buffer. Chris@16: //!Does not throw. Chris@16: std::pair buffer() const Chris@16: { return get_buf().buffer(); } Chris@16: Chris@16: //!Sets the underlying buffer to a new value. Resets Chris@16: //!stream position. Does not throw. Chris@16: void buffer(const CharT *buf, std::size_t length) Chris@16: { get_buf().buffer(const_cast(buf), length); } Chris@16: }; Chris@16: Chris@16: //!A basic_ostream class that uses a fixed size character buffer Chris@16: //!as its formatting buffer. Chris@16: template Chris@16: class basic_obufferstream : Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private basic_bufferbuf, Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: public std::basic_ostream Chris@16: { Chris@16: public: Chris@16: typedef typename std::basic_ios Chris@16: ::char_type char_type; Chris@16: typedef typename std::basic_ios::int_type int_type; Chris@16: typedef typename std::basic_ios::pos_type pos_type; Chris@16: typedef typename std::basic_ios::off_type off_type; Chris@16: typedef typename std::basic_ios::traits_type traits_type; Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private: Chris@16: typedef basic_bufferbuf bufferbuf_t; Chris@16: typedef std::basic_ios basic_ios_t; Chris@16: typedef std::basic_ostream base_t; Chris@16: bufferbuf_t & get_buf() { return *this; } Chris@16: const bufferbuf_t & get_buf() const{ return *this; } Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: //!Constructor. Chris@16: //!Does not throw. Chris@16: basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out) Chris@16: : //basic_ios_t() is called first (lefting it uninitialized) as it's a Chris@16: //virtual base of basic_istream. The class will be initialized when Chris@16: //basic_istream is constructed calling basic_ios_t::init(). Chris@16: //As bufferbuf_t's constructor does not throw there is no risk of Chris@16: //calling the basic_ios_t's destructor without calling basic_ios_t::init() Chris@16: bufferbuf_t(mode | std::ios_base::out) Chris@16: , base_t(&get_buf()) Chris@16: {} Chris@16: Chris@16: //!Constructor. Assigns formatting buffer. Chris@16: //!Does not throw. Chris@16: basic_obufferstream(CharT *buf, std::size_t length, Chris@16: std::ios_base::openmode mode = std::ios_base::out) Chris@16: : //basic_ios_t() is called first (lefting it uninitialized) as it's a Chris@16: //virtual base of basic_istream. The class will be initialized when Chris@16: //basic_istream is constructed calling basic_ios_t::init(). Chris@16: //As bufferbuf_t's constructor does not throw there is no risk of Chris@16: //calling the basic_ios_t's destructor without calling basic_ios_t::init() Chris@16: bufferbuf_t(buf, length, mode | std::ios_base::out) Chris@16: , base_t(&get_buf()) Chris@16: {} Chris@16: Chris@16: ~basic_obufferstream(){} Chris@16: Chris@16: public: Chris@16: //!Returns the address of the stored Chris@16: //!stream buffer. Chris@16: basic_bufferbuf* rdbuf() const Chris@16: { return const_cast*>(&get_buf()); } Chris@16: Chris@16: //!Returns the pointer and size of the internal buffer. Chris@16: //!Does not throw. Chris@16: std::pair buffer() const Chris@16: { return get_buf().buffer(); } Chris@16: Chris@16: //!Sets the underlying buffer to a new value. Resets Chris@16: //!stream position. Does not throw. Chris@16: void buffer(CharT *buf, std::size_t length) Chris@16: { get_buf().buffer(buf, length); } Chris@16: }; Chris@16: Chris@16: Chris@16: //!A basic_iostream class that uses a fixed size character buffer Chris@16: //!as its formatting buffer. Chris@16: template Chris@16: class basic_bufferstream : Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private basic_bufferbuf, Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: public std::basic_iostream Chris@16: { Chris@16: public: // Typedefs Chris@16: typedef typename std::basic_ios Chris@16: ::char_type char_type; Chris@16: typedef typename std::basic_ios::int_type int_type; Chris@16: typedef typename std::basic_ios::pos_type pos_type; Chris@16: typedef typename std::basic_ios::off_type off_type; Chris@16: typedef typename std::basic_ios::traits_type traits_type; Chris@16: Chris@101: #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) Chris@16: private: Chris@16: typedef basic_bufferbuf bufferbuf_t; Chris@16: typedef std::basic_ios basic_ios_t; Chris@16: typedef std::basic_iostream base_t; Chris@16: bufferbuf_t & get_buf() { return *this; } Chris@16: const bufferbuf_t & get_buf() const{ return *this; } Chris@101: #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED Chris@16: Chris@16: public: Chris@16: //!Constructor. Chris@16: //!Does not throw. Chris@16: basic_bufferstream(std::ios_base::openmode mode Chris@16: = std::ios_base::in | std::ios_base::out) Chris@16: : //basic_ios_t() is called first (lefting it uninitialized) as it's a Chris@16: //virtual base of basic_istream. The class will be initialized when Chris@16: //basic_istream is constructed calling basic_ios_t::init(). Chris@16: //As bufferbuf_t's constructor does not throw there is no risk of Chris@16: //calling the basic_ios_t's destructor without calling basic_ios_t::init() Chris@16: bufferbuf_t(mode) Chris@16: , base_t(&get_buf()) Chris@16: {} Chris@16: Chris@16: //!Constructor. Assigns formatting buffer. Chris@16: //!Does not throw. Chris@16: basic_bufferstream(CharT *buf, std::size_t length, Chris@16: std::ios_base::openmode mode Chris@16: = std::ios_base::in | std::ios_base::out) Chris@16: : //basic_ios_t() is called first (lefting it uninitialized) as it's a Chris@16: //virtual base of basic_istream. The class will be initialized when Chris@16: //basic_istream is constructed calling basic_ios_t::init(). Chris@16: //As bufferbuf_t's constructor does not throw there is no risk of Chris@16: //calling the basic_ios_t's destructor without calling basic_ios_t::init() Chris@16: bufferbuf_t(buf, length, mode) Chris@16: , base_t(&get_buf()) Chris@16: {} Chris@16: Chris@16: ~basic_bufferstream(){} Chris@16: Chris@16: public: Chris@16: //!Returns the address of the stored Chris@16: //!stream buffer. Chris@16: basic_bufferbuf* rdbuf() const Chris@16: { return const_cast*>(&get_buf()); } Chris@16: Chris@16: //!Returns the pointer and size of the internal buffer. Chris@16: //!Does not throw. Chris@16: std::pair buffer() const Chris@16: { return get_buf().buffer(); } Chris@16: Chris@16: //!Sets the underlying buffer to a new value. Resets Chris@16: //!stream position. Does not throw. Chris@16: void buffer(CharT *buf, std::size_t length) Chris@16: { get_buf().buffer(buf, length); } Chris@16: }; Chris@16: Chris@16: //Some typedefs to simplify usage Chris@16: typedef basic_bufferbuf bufferbuf; Chris@16: typedef basic_bufferstream bufferstream; Chris@16: typedef basic_ibufferstream ibufferstream; Chris@16: typedef basic_obufferstream obufferstream; Chris@16: Chris@16: typedef basic_bufferbuf wbufferbuf; Chris@16: typedef basic_bufferstream wbufferstream; Chris@16: typedef basic_ibufferstream wibufferstream; Chris@16: typedef basic_obufferstream wobufferstream; Chris@16: Chris@16: Chris@16: }} //namespace boost { namespace interprocess { Chris@16: Chris@16: #include Chris@16: Chris@16: #endif /* BOOST_INTERPROCESS_BUFFERSTREAM_HPP */