Line data Source code
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> basic_streambuf_t;
74 :
75 : public:
76 : //!Constructor.
77 : //!Does not throw.
78 : explicit basic_bufferbuf(std::ios_base::openmode mode
79 : = std::ios_base::in | std::ios_base::out)
80 : : basic_streambuf_t(), m_mode(mode), m_buffer(0), m_length(0)
81 : {}
82 :
83 : //!Constructor. Assigns formatting buffer.
84 : //!Does not throw.
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 : : basic_streambuf_t(), m_mode(mode), m_buffer(buf), m_length(length)
89 : { this->set_pointers(); }
90 :
91 : virtual ~basic_bufferbuf(){}
92 :
93 : public:
94 : //!Returns the pointer and size of the internal buffer.
95 : //!Does not throw.
96 : 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.
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:
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:
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 :
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 :
150 0 : virtual int_type overflow(int_type c = CharTraits::eof())
151 : {
152 0 : if(m_mode & std::ios_base::out) {
153 0 : 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 0 : if(this->pptr() == this->epptr()) {
165 : //We can't append to a static buffer
166 : return CharTraits::eof();
167 : }
168 : else {
169 0 : *this->pptr() = CharTraits::to_char_type(c);
170 0 : this->pbump(1);
171 0 : 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 :
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(static_cast<int>(off));
242 : }
243 : }
244 :
245 : return pos_type(off);
246 : }
247 :
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> basic_streambuf_t;
281 : bufferbuf_t & get_buf() { return *this; }
282 : const bufferbuf_t & get_buf() const{ return *this; }
283 : #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
284 :
285 : public:
286 : //!Constructor.
287 : //!Does not throw.
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 : , basic_streambuf_t(this)
296 : {}
297 :
298 : //!Constructor. Assigns formatting buffer.
299 : //!Does not throw.
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 : , basic_streambuf_t(this)
309 : {}
310 :
311 : ~basic_ibufferstream(){}
312 :
313 : public:
314 : //!Returns the address of the stored
315 : //!stream buffer.
316 : 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.
321 : 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.
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> basic_ostream_t;
352 : bufferbuf_t & get_buf() { return *this; }
353 : const bufferbuf_t & get_buf() const{ return *this; }
354 : #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
355 :
356 : public:
357 : //!Constructor.
358 : //!Does not throw.
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 : , basic_ostream_t(this)
367 : {}
368 :
369 : //!Constructor. Assigns formatting buffer.
370 : //!Does not throw.
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 : , basic_ostream_t(this)
380 : {}
381 :
382 : ~basic_obufferstream(){}
383 :
384 : public:
385 : //!Returns the address of the stored
386 : //!stream buffer.
387 : 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.
392 : 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.
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> basic_iostream_t;
424 : bufferbuf_t & get_buf() { return *this; }
425 : const bufferbuf_t & get_buf() const{ return *this; }
426 : #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED
427 :
428 : public:
429 : //!Constructor.
430 : //!Does not throw.
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 : , basic_iostream_t(this)
440 : {}
441 :
442 : //!Constructor. Assigns formatting buffer.
443 : //!Does not throw.
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 : , basic_iostream_t(this)
454 : {}
455 :
456 : ~basic_bufferstream(){}
457 :
458 : public:
459 : //!Returns the address of the stored
460 : //!stream buffer.
461 : 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.
466 : 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.
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 */
|