vectorstream.hpp 25 KB

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