]>
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 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; | |
b32b8144 | 73 | typedef std::basic_streambuf<char_type, traits_type> basic_streambuf_t; |
7c673cae FG |
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) | |
b32b8144 | 80 | : basic_streambuf_t(), m_mode(mode), m_buffer(0), m_length(0) |
7c673cae FG |
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) | |
b32b8144 | 88 | : basic_streambuf_t(), m_mode(mode), m_buffer(buf), m_length(length) |
7c673cae FG |
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 | 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 | ||
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 | ||
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; | |
b32b8144 | 280 | typedef std::basic_istream<char_type, CharTraits> basic_streambuf_t; |
7c673cae FG |
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) | |
b32b8144 | 295 | , basic_streambuf_t(this) |
7c673cae FG |
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) | |
b32b8144 | 308 | , basic_streambuf_t(this) |
7c673cae FG |
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; | |
b32b8144 | 351 | typedef std::basic_ostream<char_type, CharTraits> basic_ostream_t; |
7c673cae FG |
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) | |
b32b8144 | 366 | , basic_ostream_t(this) |
7c673cae FG |
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) | |
b32b8144 | 379 | , basic_ostream_t(this) |
7c673cae FG |
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; | |
b32b8144 | 423 | typedef std::basic_iostream<char_type, CharTraits> basic_iostream_t; |
7c673cae FG |
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) | |
b32b8144 | 439 | , basic_iostream_t(this) |
7c673cae FG |
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) | |
b32b8144 | 453 | , basic_iostream_t(this) |
7c673cae FG |
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 */ |