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 buffer. 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_bufferbuf, basic_ibufferstream, 31 //!basic_obufferstream, and basic_bufferstream classes. These classes 32 //!represent streamsbufs and streams whose sources or destinations 33 //!are fixed size character buffers. 34 35 #ifndef BOOST_INTERPROCESS_BUFFERSTREAM_HPP 36 #define BOOST_INTERPROCESS_BUFFERSTREAM_HPP 37 38 #ifndef BOOST_CONFIG_HPP 39 # include <boost/config.hpp> 40 #endif 41 # 42 #if defined(BOOST_HAS_PRAGMA_ONCE) 43 # pragma once 44 #endif 45 46 #include <boost/interprocess/detail/config_begin.hpp> 47 #include <boost/interprocess/detail/workaround.hpp> 48 49 #include <iosfwd> 50 #include <ios> 51 #include <istream> 52 #include <ostream> 53 #include <string> // char traits 54 #include <cstddef> // ptrdiff_t 55 #include <boost/assert.hpp> 56 #include <boost/interprocess/interprocess_fwd.hpp> 57 58 namespace boost { namespace interprocess { 59 60 //!A streambuf class that controls the transmission of elements to and from 61 //!a basic_xbufferstream. The elements are transmitted from a to a fixed 62 //!size buffer 63 template <class CharT, class CharTraits> 64 class basic_bufferbuf 65 : public std::basic_streambuf<CharT, CharTraits> 66 { 67 public: 68 typedef CharT char_type; 69 typedef typename CharTraits::int_type int_type; 70 typedef typename CharTraits::pos_type pos_type; 71 typedef typename CharTraits::off_type off_type; 72 typedef CharTraits traits_type; 73 typedef std::basic_streambuf<char_type, traits_type> base_t; 74 75 public: 76 //!Constructor. 77 //!Does not throw. basic_bufferbuf(std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)78 explicit basic_bufferbuf(std::ios_base::openmode mode 79 = std::ios_base::in | std::ios_base::out) 80 : base_t(), m_mode(mode), m_buffer(0), m_length(0) 81 {} 82 83 //!Constructor. Assigns formatting buffer. 84 //!Does not throw. basic_bufferbuf(CharT * buf,std::size_t length,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)85 explicit basic_bufferbuf(CharT *buf, std::size_t length, 86 std::ios_base::openmode mode 87 = std::ios_base::in | std::ios_base::out) 88 : base_t(), m_mode(mode), m_buffer(buf), m_length(length) 89 { this->set_pointers(); } 90 ~basic_bufferbuf()91 virtual ~basic_bufferbuf(){} 92 93 public: 94 //!Returns the pointer and size of the internal buffer. 95 //!Does not throw. buffer() const96 std::pair<CharT *, std::size_t> buffer() const 97 { return std::pair<CharT *, std::size_t>(m_buffer, m_length); } 98 99 //!Sets the underlying buffer to a new value 100 //!Does not throw. buffer(CharT * buf,std::size_t length)101 void buffer(CharT *buf, std::size_t length) 102 { m_buffer = buf; m_length = length; this->set_pointers(); } 103 104 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 105 private: set_pointers()106 void set_pointers() 107 { 108 // The initial read position is the beginning of the buffer. 109 if(m_mode & std::ios_base::in) 110 this->setg(m_buffer, m_buffer, m_buffer + m_length); 111 112 // The initial write position is the beginning of the buffer. 113 if(m_mode & std::ios_base::out) 114 this->setp(m_buffer, m_buffer + m_length); 115 } 116 117 protected: underflow()118 virtual int_type underflow() 119 { 120 // Precondition: gptr() >= egptr(). Returns a character, if available. 121 return this->gptr() != this->egptr() ? 122 CharTraits::to_int_type(*this->gptr()) : CharTraits::eof(); 123 } 124 pbackfail(int_type c=CharTraits::eof ())125 virtual int_type pbackfail(int_type c = CharTraits::eof()) 126 { 127 if(this->gptr() != this->eback()) { 128 if(!CharTraits::eq_int_type(c, CharTraits::eof())) { 129 if(CharTraits::eq(CharTraits::to_char_type(c), this->gptr()[-1])) { 130 this->gbump(-1); 131 return c; 132 } 133 else if(m_mode & std::ios_base::out) { 134 this->gbump(-1); 135 *this->gptr() = c; 136 return c; 137 } 138 else 139 return CharTraits::eof(); 140 } 141 else { 142 this->gbump(-1); 143 return CharTraits::not_eof(c); 144 } 145 } 146 else 147 return CharTraits::eof(); 148 } 149 overflow(int_type c=CharTraits::eof ())150 virtual int_type overflow(int_type c = CharTraits::eof()) 151 { 152 if(m_mode & std::ios_base::out) { 153 if(!CharTraits::eq_int_type(c, CharTraits::eof())) { 154 // if(!(m_mode & std::ios_base::in)) { 155 // if(this->pptr() != this->epptr()) { 156 // *this->pptr() = CharTraits::to_char_type(c); 157 // this->pbump(1); 158 // return c; 159 // } 160 // else 161 // return CharTraits::eof(); 162 // } 163 // else { 164 if(this->pptr() == this->epptr()) { 165 //We can't append to a static buffer 166 return CharTraits::eof(); 167 } 168 else { 169 *this->pptr() = CharTraits::to_char_type(c); 170 this->pbump(1); 171 return c; 172 } 173 // } 174 } 175 else // c is EOF, so we don't have to do anything 176 return CharTraits::not_eof(c); 177 } 178 else // Overflow always fails if it's read-only. 179 return CharTraits::eof(); 180 } 181 seekoff(off_type off,std::ios_base::seekdir dir,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)182 virtual pos_type seekoff(off_type off, std::ios_base::seekdir dir, 183 std::ios_base::openmode mode 184 = std::ios_base::in | std::ios_base::out) 185 { 186 bool in = false; 187 bool out = false; 188 189 const std::ios_base::openmode inout = 190 std::ios_base::in | std::ios_base::out; 191 192 if((mode & inout) == inout) { 193 if(dir == std::ios_base::beg || dir == std::ios_base::end) 194 in = out = true; 195 } 196 else if(mode & std::ios_base::in) 197 in = true; 198 else if(mode & std::ios_base::out) 199 out = true; 200 201 if(!in && !out) 202 return pos_type(off_type(-1)); 203 else if((in && (!(m_mode & std::ios_base::in) || (off != 0 && this->gptr() == 0) )) || 204 (out && (!(m_mode & std::ios_base::out) || (off != 0 && this->pptr() == 0)))) 205 return pos_type(off_type(-1)); 206 207 std::streamoff newoff; 208 switch(dir) { 209 case std::ios_base::beg: 210 newoff = 0; 211 break; 212 case std::ios_base::end: 213 newoff = static_cast<std::streamoff>(m_length); 214 break; 215 case std::ios_base::cur: 216 newoff = in ? static_cast<std::streamoff>(this->gptr() - this->eback()) 217 : static_cast<std::streamoff>(this->pptr() - this->pbase()); 218 break; 219 default: 220 return pos_type(off_type(-1)); 221 } 222 223 off += newoff; 224 225 if(in) { 226 std::ptrdiff_t n = this->egptr() - this->eback(); 227 228 if(off < 0 || off > n) 229 return pos_type(off_type(-1)); 230 else 231 this->setg(this->eback(), this->eback() + off, this->eback() + n); 232 } 233 234 if(out) { 235 std::ptrdiff_t n = this->epptr() - this->pbase(); 236 237 if(off < 0 || off > n) 238 return pos_type(off_type(-1)); 239 else { 240 this->setp(this->pbase(), this->pbase() + n); 241 this->pbump(off); 242 } 243 } 244 245 return pos_type(off); 246 } 247 seekpos(pos_type pos,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)248 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode mode 249 = std::ios_base::in | std::ios_base::out) 250 { return seekoff(pos - pos_type(off_type(0)), std::ios_base::beg, mode); } 251 252 private: 253 std::ios_base::openmode m_mode; 254 CharT * m_buffer; 255 std::size_t m_length; 256 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 257 }; 258 259 //!A basic_istream class that uses a fixed size character buffer 260 //!as its formatting buffer. 261 template <class CharT, class CharTraits> 262 class basic_ibufferstream : 263 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 264 private basic_bufferbuf<CharT, CharTraits>, 265 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 266 public std::basic_istream<CharT, CharTraits> 267 { 268 public: // Typedefs 269 typedef typename std::basic_ios 270 <CharT, CharTraits>::char_type char_type; 271 typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type; 272 typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type; 273 typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; 274 typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; 275 276 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 277 private: 278 typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t; 279 typedef std::basic_ios<char_type, CharTraits> basic_ios_t; 280 typedef std::basic_istream<char_type, CharTraits> base_t; get_buf()281 bufferbuf_t & get_buf() { return *this; } get_buf() const282 const bufferbuf_t & get_buf() const{ return *this; } 283 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 284 285 public: 286 //!Constructor. 287 //!Does not throw. basic_ibufferstream(std::ios_base::openmode mode=std::ios_base::in)288 basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in) 289 : //basic_ios_t() is called first (lefting it uninitialized) as it's a 290 //virtual base of basic_istream. The class will be initialized when 291 //basic_istream is constructed calling basic_ios_t::init(). 292 //As bufferbuf_t's constructor does not throw there is no risk of 293 //calling the basic_ios_t's destructor without calling basic_ios_t::init() 294 bufferbuf_t(mode | std::ios_base::in) 295 , base_t(&get_buf()) 296 {} 297 298 //!Constructor. Assigns formatting buffer. 299 //!Does not throw. basic_ibufferstream(const CharT * buf,std::size_t length,std::ios_base::openmode mode=std::ios_base::in)300 basic_ibufferstream(const CharT *buf, std::size_t length, 301 std::ios_base::openmode mode = std::ios_base::in) 302 : //basic_ios_t() is called first (lefting it uninitialized) as it's a 303 //virtual base of basic_istream. The class will be initialized when 304 //basic_istream is constructed calling basic_ios_t::init(). 305 //As bufferbuf_t's constructor does not throw there is no risk of 306 //calling the basic_ios_t's destructor without calling basic_ios_t::init() 307 bufferbuf_t(const_cast<CharT*>(buf), length, mode | std::ios_base::in) 308 , base_t(&get_buf()) 309 {} 310 ~basic_ibufferstream()311 ~basic_ibufferstream(){}; 312 313 public: 314 //!Returns the address of the stored 315 //!stream buffer. rdbuf() const316 basic_bufferbuf<CharT, CharTraits>* rdbuf() const 317 { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); } 318 319 //!Returns the pointer and size of the internal buffer. 320 //!Does not throw. buffer() const321 std::pair<const CharT *, std::size_t> buffer() const 322 { return get_buf().buffer(); } 323 324 //!Sets the underlying buffer to a new value. Resets 325 //!stream position. Does not throw. buffer(const CharT * buf,std::size_t length)326 void buffer(const CharT *buf, std::size_t length) 327 { get_buf().buffer(const_cast<CharT*>(buf), length); } 328 }; 329 330 //!A basic_ostream class that uses a fixed size character buffer 331 //!as its formatting buffer. 332 template <class CharT, class CharTraits> 333 class basic_obufferstream : 334 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 335 private basic_bufferbuf<CharT, CharTraits>, 336 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 337 public std::basic_ostream<CharT, CharTraits> 338 { 339 public: 340 typedef typename std::basic_ios 341 <CharT, CharTraits>::char_type char_type; 342 typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type; 343 typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type; 344 typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; 345 typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; 346 347 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 348 private: 349 typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t; 350 typedef std::basic_ios<char_type, CharTraits> basic_ios_t; 351 typedef std::basic_ostream<char_type, CharTraits> base_t; get_buf()352 bufferbuf_t & get_buf() { return *this; } get_buf() const353 const bufferbuf_t & get_buf() const{ return *this; } 354 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 355 356 public: 357 //!Constructor. 358 //!Does not throw. basic_obufferstream(std::ios_base::openmode mode=std::ios_base::out)359 basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out) 360 : //basic_ios_t() is called first (lefting it uninitialized) as it's a 361 //virtual base of basic_istream. The class will be initialized when 362 //basic_istream is constructed calling basic_ios_t::init(). 363 //As bufferbuf_t's constructor does not throw there is no risk of 364 //calling the basic_ios_t's destructor without calling basic_ios_t::init() 365 bufferbuf_t(mode | std::ios_base::out) 366 , base_t(&get_buf()) 367 {} 368 369 //!Constructor. Assigns formatting buffer. 370 //!Does not throw. basic_obufferstream(CharT * buf,std::size_t length,std::ios_base::openmode mode=std::ios_base::out)371 basic_obufferstream(CharT *buf, std::size_t length, 372 std::ios_base::openmode mode = std::ios_base::out) 373 : //basic_ios_t() is called first (lefting it uninitialized) as it's a 374 //virtual base of basic_istream. The class will be initialized when 375 //basic_istream is constructed calling basic_ios_t::init(). 376 //As bufferbuf_t's constructor does not throw there is no risk of 377 //calling the basic_ios_t's destructor without calling basic_ios_t::init() 378 bufferbuf_t(buf, length, mode | std::ios_base::out) 379 , base_t(&get_buf()) 380 {} 381 ~basic_obufferstream()382 ~basic_obufferstream(){} 383 384 public: 385 //!Returns the address of the stored 386 //!stream buffer. rdbuf() const387 basic_bufferbuf<CharT, CharTraits>* rdbuf() const 388 { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); } 389 390 //!Returns the pointer and size of the internal buffer. 391 //!Does not throw. buffer() const392 std::pair<CharT *, std::size_t> buffer() const 393 { return get_buf().buffer(); } 394 395 //!Sets the underlying buffer to a new value. Resets 396 //!stream position. Does not throw. buffer(CharT * buf,std::size_t length)397 void buffer(CharT *buf, std::size_t length) 398 { get_buf().buffer(buf, length); } 399 }; 400 401 402 //!A basic_iostream class that uses a fixed size character buffer 403 //!as its formatting buffer. 404 template <class CharT, class CharTraits> 405 class basic_bufferstream : 406 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 407 private basic_bufferbuf<CharT, CharTraits>, 408 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 409 public std::basic_iostream<CharT, CharTraits> 410 { 411 public: // Typedefs 412 typedef typename std::basic_ios 413 <CharT, CharTraits>::char_type char_type; 414 typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type; 415 typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type; 416 typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type; 417 typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type; 418 419 #if !defined(BOOST_INTERPROCESS_DOXYGEN_INVOKED) 420 private: 421 typedef basic_bufferbuf<CharT, CharTraits> bufferbuf_t; 422 typedef std::basic_ios<char_type, CharTraits> basic_ios_t; 423 typedef std::basic_iostream<char_type, CharTraits> base_t; get_buf()424 bufferbuf_t & get_buf() { return *this; } get_buf() const425 const bufferbuf_t & get_buf() const{ return *this; } 426 #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED 427 428 public: 429 //!Constructor. 430 //!Does not throw. basic_bufferstream(std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)431 basic_bufferstream(std::ios_base::openmode mode 432 = std::ios_base::in | std::ios_base::out) 433 : //basic_ios_t() is called first (lefting it uninitialized) as it's a 434 //virtual base of basic_istream. The class will be initialized when 435 //basic_istream is constructed calling basic_ios_t::init(). 436 //As bufferbuf_t's constructor does not throw there is no risk of 437 //calling the basic_ios_t's destructor without calling basic_ios_t::init() 438 bufferbuf_t(mode) 439 , base_t(&get_buf()) 440 {} 441 442 //!Constructor. Assigns formatting buffer. 443 //!Does not throw. basic_bufferstream(CharT * buf,std::size_t length,std::ios_base::openmode mode=std::ios_base::in|std::ios_base::out)444 basic_bufferstream(CharT *buf, std::size_t length, 445 std::ios_base::openmode mode 446 = std::ios_base::in | std::ios_base::out) 447 : //basic_ios_t() is called first (lefting it uninitialized) as it's a 448 //virtual base of basic_istream. The class will be initialized when 449 //basic_istream is constructed calling basic_ios_t::init(). 450 //As bufferbuf_t's constructor does not throw there is no risk of 451 //calling the basic_ios_t's destructor without calling basic_ios_t::init() 452 bufferbuf_t(buf, length, mode) 453 , base_t(&get_buf()) 454 {} 455 ~basic_bufferstream()456 ~basic_bufferstream(){} 457 458 public: 459 //!Returns the address of the stored 460 //!stream buffer. rdbuf() const461 basic_bufferbuf<CharT, CharTraits>* rdbuf() const 462 { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&get_buf()); } 463 464 //!Returns the pointer and size of the internal buffer. 465 //!Does not throw. buffer() const466 std::pair<CharT *, std::size_t> buffer() const 467 { return get_buf().buffer(); } 468 469 //!Sets the underlying buffer to a new value. Resets 470 //!stream position. Does not throw. buffer(CharT * buf,std::size_t length)471 void buffer(CharT *buf, std::size_t length) 472 { get_buf().buffer(buf, length); } 473 }; 474 475 //Some typedefs to simplify usage 476 typedef basic_bufferbuf<char> bufferbuf; 477 typedef basic_bufferstream<char> bufferstream; 478 typedef basic_ibufferstream<char> ibufferstream; 479 typedef basic_obufferstream<char> obufferstream; 480 481 typedef basic_bufferbuf<wchar_t> wbufferbuf; 482 typedef basic_bufferstream<wchar_t> wbufferstream; 483 typedef basic_ibufferstream<wchar_t> wibufferstream; 484 typedef basic_obufferstream<wchar_t> wobufferstream; 485 486 487 }} //namespace boost { namespace interprocess { 488 489 #include <boost/interprocess/detail/config_end.hpp> 490 491 #endif /* BOOST_INTERPROCESS_BUFFERSTREAM_HPP */ 492