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