/Src/Dependencies/Boost/boost/iostreams/detail/streambuf/direct_streambuf.hpp

http://hadesmem.googlecode.com/ · C++ Header · 313 lines · 266 code · 35 blank · 12 comment · 62 complexity · be43b9025cd432578e7af48066323903 MD5 · raw file

  1. // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
  2. // (C) Copyright 2003-2007 Jonathan Turkanis
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
  5. // See http://www.boost.org/libs/iostreams for documentation.
  6. #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED
  7. #define BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED
  8. #if defined(_MSC_VER) && (_MSC_VER >= 1020)
  9. # pragma once
  10. #endif
  11. #include <boost/assert.hpp>
  12. #include <cstddef>
  13. #include <typeinfo>
  14. #include <utility> // pair.
  15. #include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME,
  16. #include <boost/iostreams/detail/char_traits.hpp> // member template friends.
  17. #include <boost/iostreams/detail/config/wide_streams.hpp>
  18. #include <boost/iostreams/detail/error.hpp>
  19. #include <boost/iostreams/detail/execute.hpp>
  20. #include <boost/iostreams/detail/functional.hpp>
  21. #include <boost/iostreams/detail/ios.hpp>
  22. #include <boost/iostreams/detail/optional.hpp>
  23. #include <boost/iostreams/detail/streambuf.hpp>
  24. #include <boost/iostreams/detail/streambuf/linked_streambuf.hpp>
  25. #include <boost/iostreams/operations.hpp>
  26. #include <boost/iostreams/positioning.hpp>
  27. #include <boost/iostreams/traits.hpp>
  28. #include <boost/throw_exception.hpp>
  29. // Must come last.
  30. #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
  31. namespace boost { namespace iostreams {
  32. namespace detail {
  33. template< typename T,
  34. typename Tr =
  35. BOOST_IOSTREAMS_CHAR_TRAITS(
  36. BOOST_DEDUCED_TYPENAME char_type_of<T>::type
  37. ) >
  38. class direct_streambuf
  39. : public linked_streambuf<BOOST_DEDUCED_TYPENAME char_type_of<T>::type, Tr>
  40. {
  41. public:
  42. typedef typename char_type_of<T>::type char_type;
  43. BOOST_IOSTREAMS_STREAMBUF_TYPEDEFS(Tr)
  44. private:
  45. typedef linked_streambuf<char_type, traits_type> base_type;
  46. typedef typename category_of<T>::type category;
  47. typedef BOOST_IOSTREAMS_BASIC_STREAMBUF(
  48. char_type, traits_type
  49. ) streambuf_type;
  50. public: // stream needs access.
  51. void open(const T& t, std::streamsize buffer_size,
  52. std::streamsize pback_size);
  53. bool is_open() const;
  54. void close();
  55. bool auto_close() const { return auto_close_; }
  56. void set_auto_close(bool close) { auto_close_ = close; }
  57. bool strict_sync() { return true; }
  58. // Declared in linked_streambuf.
  59. T* component() { return storage_.get(); }
  60. protected:
  61. #if !BOOST_WORKAROUND(__GNUC__, == 2)
  62. BOOST_IOSTREAMS_USING_PROTECTED_STREAMBUF_MEMBERS(base_type)
  63. #endif
  64. direct_streambuf();
  65. //--------------Virtual functions-----------------------------------------//
  66. // Declared in linked_streambuf.
  67. void close_impl(BOOST_IOS::openmode m);
  68. const std::type_info& component_type() const { return typeid(T); }
  69. void* component_impl() { return component(); }
  70. #ifdef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES
  71. public:
  72. #endif
  73. // Declared in basic_streambuf.
  74. int_type underflow();
  75. int_type pbackfail(int_type c);
  76. int_type overflow(int_type c);
  77. pos_type seekoff( off_type off, BOOST_IOS::seekdir way,
  78. BOOST_IOS::openmode which );
  79. pos_type seekpos(pos_type sp, BOOST_IOS::openmode which);
  80. private:
  81. pos_type seek_impl( stream_offset off, BOOST_IOS::seekdir way,
  82. BOOST_IOS::openmode which );
  83. void init_input(any_tag) { }
  84. void init_input(input);
  85. void init_output(any_tag) { }
  86. void init_output(output);
  87. void init_get_area();
  88. void init_put_area();
  89. bool one_head() const;
  90. bool two_head() const;
  91. optional<T> storage_;
  92. char_type *ibeg_, *iend_, *obeg_, *oend_;
  93. bool auto_close_;
  94. };
  95. //------------------Implementation of direct_streambuf------------------------//
  96. template<typename T, typename Tr>
  97. direct_streambuf<T, Tr>::direct_streambuf()
  98. : ibeg_(0), iend_(0), obeg_(0), oend_(0), auto_close_(true)
  99. { this->set_true_eof(true); }
  100. template<typename T, typename Tr>
  101. void direct_streambuf<T, Tr>::open
  102. (const T& t, std::streamsize, std::streamsize)
  103. {
  104. storage_.reset(t);
  105. init_input(category());
  106. init_output(category());
  107. setg(0, 0, 0);
  108. setp(0, 0);
  109. this->set_needs_close();
  110. }
  111. template<typename T, typename Tr>
  112. bool direct_streambuf<T, Tr>::is_open() const
  113. { return ibeg_ != 0 || obeg_ != 0; }
  114. template<typename T, typename Tr>
  115. void direct_streambuf<T, Tr>::close()
  116. {
  117. base_type* self = this;
  118. detail::execute_all( detail::call_member_close(*self, BOOST_IOS::in),
  119. detail::call_member_close(*self, BOOST_IOS::out),
  120. detail::call_reset(storage_) );
  121. }
  122. template<typename T, typename Tr>
  123. typename direct_streambuf<T, Tr>::int_type
  124. direct_streambuf<T, Tr>::underflow()
  125. {
  126. if (!ibeg_)
  127. boost::throw_exception(cant_read());
  128. if (!gptr())
  129. init_get_area();
  130. return gptr() != iend_ ?
  131. traits_type::to_int_type(*gptr()) :
  132. traits_type::eof();
  133. }
  134. template<typename T, typename Tr>
  135. typename direct_streambuf<T, Tr>::int_type
  136. direct_streambuf<T, Tr>::pbackfail(int_type c)
  137. {
  138. using namespace std;
  139. if (!ibeg_)
  140. boost::throw_exception(cant_read());
  141. if (gptr() != 0 && gptr() != ibeg_) {
  142. gbump(-1);
  143. if (!traits_type::eq_int_type(c, traits_type::eof()))
  144. *gptr() = traits_type::to_char_type(c);
  145. return traits_type::not_eof(c);
  146. }
  147. boost::throw_exception(bad_putback());
  148. }
  149. template<typename T, typename Tr>
  150. typename direct_streambuf<T, Tr>::int_type
  151. direct_streambuf<T, Tr>::overflow(int_type c)
  152. {
  153. using namespace std;
  154. if (!obeg_)
  155. boost::throw_exception(BOOST_IOSTREAMS_FAILURE("no write access"));
  156. if (!pptr()) init_put_area();
  157. if (!traits_type::eq_int_type(c, traits_type::eof())) {
  158. if (pptr() == oend_)
  159. boost::throw_exception(
  160. BOOST_IOSTREAMS_FAILURE("write area exhausted")
  161. );
  162. *pptr() = traits_type::to_char_type(c);
  163. pbump(1);
  164. return c;
  165. }
  166. return traits_type::not_eof(c);
  167. }
  168. template<typename T, typename Tr>
  169. inline typename direct_streambuf<T, Tr>::pos_type
  170. direct_streambuf<T, Tr>::seekoff
  171. (off_type off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
  172. { return seek_impl(off, way, which); }
  173. template<typename T, typename Tr>
  174. inline typename direct_streambuf<T, Tr>::pos_type
  175. direct_streambuf<T, Tr>::seekpos
  176. (pos_type sp, BOOST_IOS::openmode which)
  177. {
  178. return seek_impl(position_to_offset(sp), BOOST_IOS::beg, which);
  179. }
  180. template<typename T, typename Tr>
  181. void direct_streambuf<T, Tr>::close_impl(BOOST_IOS::openmode which)
  182. {
  183. if (which == BOOST_IOS::in && ibeg_ != 0) {
  184. setg(0, 0, 0);
  185. ibeg_ = iend_ = 0;
  186. }
  187. if (which == BOOST_IOS::out && obeg_ != 0) {
  188. sync();
  189. setp(0, 0);
  190. obeg_ = oend_ = 0;
  191. }
  192. boost::iostreams::close(*storage_, which);
  193. }
  194. template<typename T, typename Tr>
  195. typename direct_streambuf<T, Tr>::pos_type direct_streambuf<T, Tr>::seek_impl
  196. (stream_offset off, BOOST_IOS::seekdir way, BOOST_IOS::openmode which)
  197. {
  198. using namespace std;
  199. BOOST_IOS::openmode both = BOOST_IOS::in | BOOST_IOS::out;
  200. if (two_head() && (which & both) == both)
  201. boost::throw_exception(bad_seek());
  202. stream_offset result = -1;
  203. bool one = one_head();
  204. if (one && (pptr() != 0 || gptr()== 0))
  205. init_get_area(); // Switch to input mode, for code reuse.
  206. if (one || ((which & BOOST_IOS::in) != 0 && ibeg_ != 0)) {
  207. if (!gptr()) setg(ibeg_, ibeg_, iend_);
  208. ptrdiff_t next = 0;
  209. switch (way) {
  210. case BOOST_IOS::beg: next = off; break;
  211. case BOOST_IOS::cur: next = (gptr() - ibeg_) + off; break;
  212. case BOOST_IOS::end: next = (iend_ - ibeg_) + off; break;
  213. default: BOOST_ASSERT(0);
  214. }
  215. if (next < 0 || next > (iend_ - ibeg_))
  216. boost::throw_exception(bad_seek());
  217. setg(ibeg_, ibeg_ + next, iend_);
  218. result = next;
  219. }
  220. if (!one && (which & BOOST_IOS::out) != 0 && obeg_ != 0) {
  221. if (!pptr()) setp(obeg_, oend_);
  222. ptrdiff_t next = 0;
  223. switch (way) {
  224. case BOOST_IOS::beg: next = off; break;
  225. case BOOST_IOS::cur: next = (pptr() - obeg_) + off; break;
  226. case BOOST_IOS::end: next = (oend_ - obeg_) + off; break;
  227. default: BOOST_ASSERT(0);
  228. }
  229. if (next < 0 || next > (oend_ - obeg_))
  230. boost::throw_exception(bad_seek());
  231. pbump(static_cast<int>(next - (pptr() - obeg_)));
  232. result = next;
  233. }
  234. return offset_to_position(result);
  235. }
  236. template<typename T, typename Tr>
  237. void direct_streambuf<T, Tr>::init_input(input)
  238. {
  239. std::pair<char_type*, char_type*> p = input_sequence(*storage_);
  240. ibeg_ = p.first;
  241. iend_ = p.second;
  242. }
  243. template<typename T, typename Tr>
  244. void direct_streambuf<T, Tr>::init_output(output)
  245. {
  246. std::pair<char_type*, char_type*> p = output_sequence(*storage_);
  247. obeg_ = p.first;
  248. oend_ = p.second;
  249. }
  250. template<typename T, typename Tr>
  251. void direct_streambuf<T, Tr>::init_get_area()
  252. {
  253. setg(ibeg_, ibeg_, iend_);
  254. if (one_head() && pptr()) {
  255. gbump(static_cast<int>(pptr() - obeg_));
  256. setp(0, 0);
  257. }
  258. }
  259. template<typename T, typename Tr>
  260. void direct_streambuf<T, Tr>::init_put_area()
  261. {
  262. setp(obeg_, oend_);
  263. if (one_head() && gptr()) {
  264. pbump(static_cast<int>(gptr() - ibeg_));
  265. setg(0, 0, 0);
  266. }
  267. }
  268. template<typename T, typename Tr>
  269. inline bool direct_streambuf<T, Tr>::one_head() const
  270. { return ibeg_ && obeg_ && ibeg_ == obeg_; }
  271. template<typename T, typename Tr>
  272. inline bool direct_streambuf<T, Tr>::two_head() const
  273. { return ibeg_ && obeg_ && ibeg_ != obeg_; }
  274. //----------------------------------------------------------------------------//
  275. } // End namespace detail.
  276. } } // End namespaces iostreams, boost.
  277. #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC
  278. #endif // #ifndef BOOST_IOSTREAMS_DETAIL_DIRECT_STREAMBUF_HPP_INCLUDED