bufferstream.hpp 18 KB

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