bufferstream.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. : public std::basic_istream<CharT, CharTraits>
  226. {
  227. public: // Typedefs
  228. typedef typename std::basic_ios
  229. <CharT, CharTraits>::char_type char_type;
  230. typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
  231. typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
  232. typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
  233. typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
  234. private:
  235. typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
  236. typedef std::basic_istream<char_type, CharTraits> base_t;
  237. public:
  238. //!Constructor.
  239. //!Does not throw.
  240. basic_ibufferstream(std::ios_base::openmode mode = std::ios_base::in)
  241. : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::in)
  242. { basic_ios_t::init(&m_buf); }
  243. //!Constructor. Assigns formatting buffer.
  244. //!Does not throw.
  245. basic_ibufferstream(const CharT *buf, std::size_t length,
  246. std::ios_base::openmode mode = std::ios_base::in)
  247. : basic_ios_t(), base_t(0),
  248. m_buf(const_cast<CharT*>(buf), length, mode | std::ios_base::in)
  249. { basic_ios_t::init(&m_buf); }
  250. ~basic_ibufferstream(){};
  251. public:
  252. //!Returns the address of the stored
  253. //!stream buffer.
  254. basic_bufferbuf<CharT, CharTraits>* rdbuf() const
  255. { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
  256. //!Returns the pointer and size of the internal buffer.
  257. //!Does not throw.
  258. std::pair<const CharT *, std::size_t> buffer() const
  259. { return m_buf.buffer(); }
  260. //!Sets the underlying buffer to a new value. Resets
  261. //!stream position. Does not throw.
  262. void buffer(const CharT *buf, std::size_t length)
  263. { m_buf.buffer(const_cast<CharT*>(buf), length); }
  264. /// @cond
  265. private:
  266. basic_bufferbuf<CharT, CharTraits> m_buf;
  267. /// @endcond
  268. };
  269. //!A basic_ostream class that uses a fixed size character buffer
  270. //!as its formatting buffer.
  271. template <class CharT, class CharTraits>
  272. class basic_obufferstream
  273. : public std::basic_ostream<CharT, CharTraits>
  274. {
  275. public:
  276. typedef typename std::basic_ios
  277. <CharT, CharTraits>::char_type char_type;
  278. typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
  279. typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
  280. typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
  281. typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
  282. /// @cond
  283. private:
  284. typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
  285. typedef std::basic_ostream<char_type, CharTraits> base_t;
  286. /// @endcond
  287. public:
  288. //!Constructor.
  289. //!Does not throw.
  290. basic_obufferstream(std::ios_base::openmode mode = std::ios_base::out)
  291. : basic_ios_t(), base_t(0), m_buf(mode | std::ios_base::out)
  292. { basic_ios_t::init(&m_buf); }
  293. //!Constructor. Assigns formatting buffer.
  294. //!Does not throw.
  295. basic_obufferstream(CharT *buf, std::size_t length,
  296. std::ios_base::openmode mode = std::ios_base::out)
  297. : basic_ios_t(), base_t(0),
  298. m_buf(buf, length, mode | std::ios_base::out)
  299. { basic_ios_t::init(&m_buf); }
  300. ~basic_obufferstream(){}
  301. public:
  302. //!Returns the address of the stored
  303. //!stream buffer.
  304. basic_bufferbuf<CharT, CharTraits>* rdbuf() const
  305. { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
  306. //!Returns the pointer and size of the internal buffer.
  307. //!Does not throw.
  308. std::pair<CharT *, std::size_t> buffer() const
  309. { return m_buf.buffer(); }
  310. //!Sets the underlying buffer to a new value. Resets
  311. //!stream position. Does not throw.
  312. void buffer(CharT *buf, std::size_t length)
  313. { m_buf.buffer(buf, length); }
  314. /// @cond
  315. private:
  316. basic_bufferbuf<CharT, CharTraits> m_buf;
  317. /// @endcond
  318. };
  319. //!A basic_iostream class that uses a fixed size character buffer
  320. //!as its formatting buffer.
  321. template <class CharT, class CharTraits>
  322. class basic_bufferstream
  323. : public std::basic_iostream<CharT, CharTraits>
  324. {
  325. public: // Typedefs
  326. typedef typename std::basic_ios
  327. <CharT, CharTraits>::char_type char_type;
  328. typedef typename std::basic_ios<char_type, CharTraits>::int_type int_type;
  329. typedef typename std::basic_ios<char_type, CharTraits>::pos_type pos_type;
  330. typedef typename std::basic_ios<char_type, CharTraits>::off_type off_type;
  331. typedef typename std::basic_ios<char_type, CharTraits>::traits_type traits_type;
  332. /// @cond
  333. private:
  334. typedef std::basic_ios<char_type, CharTraits> basic_ios_t;
  335. typedef std::basic_iostream<char_type, CharTraits> base_t;
  336. /// @endcond
  337. public:
  338. //!Constructor.
  339. //!Does not throw.
  340. basic_bufferstream(std::ios_base::openmode mode
  341. = std::ios_base::in | std::ios_base::out)
  342. : basic_ios_t(), base_t(0), m_buf(mode)
  343. { basic_ios_t::init(&m_buf); }
  344. //!Constructor. Assigns formatting buffer.
  345. //!Does not throw.
  346. basic_bufferstream(CharT *buf, std::size_t length,
  347. std::ios_base::openmode mode
  348. = std::ios_base::in | std::ios_base::out)
  349. : basic_ios_t(), base_t(0), m_buf(buf, length, mode)
  350. { basic_ios_t::init(&m_buf); }
  351. ~basic_bufferstream(){}
  352. public:
  353. //!Returns the address of the stored
  354. //!stream buffer.
  355. basic_bufferbuf<CharT, CharTraits>* rdbuf() const
  356. { return const_cast<basic_bufferbuf<CharT, CharTraits>*>(&m_buf); }
  357. //!Returns the pointer and size of the internal buffer.
  358. //!Does not throw.
  359. std::pair<CharT *, std::size_t> buffer() const
  360. { return m_buf.buffer(); }
  361. //!Sets the underlying buffer to a new value. Resets
  362. //!stream position. Does not throw.
  363. void buffer(CharT *buf, std::size_t length)
  364. { m_buf.buffer(buf, length); }
  365. /// @cond
  366. private:
  367. basic_bufferbuf<CharT, CharTraits> m_buf;
  368. /// @endcond
  369. };
  370. //Some typedefs to simplify usage
  371. typedef basic_bufferbuf<char> bufferbuf;
  372. typedef basic_bufferstream<char> bufferstream;
  373. typedef basic_ibufferstream<char> ibufferstream;
  374. typedef basic_obufferstream<char> obufferstream;
  375. typedef basic_bufferbuf<wchar_t> wbufferbuf;
  376. typedef basic_bufferstream<wchar_t> wbufferstream;
  377. typedef basic_ibufferstream<wchar_t> wibufferstream;
  378. typedef basic_obufferstream<wchar_t> wobufferstream;
  379. }} //namespace boost { namespace interprocess {
  380. #include <boost/interprocess/detail/config_end.hpp>
  381. #endif /* BOOST_INTERPROCESS_BUFFERSTREAM_HPP */