bufferstream.hpp 19 KB

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