buffer.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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_BUFFERS_HPP_INCLUDED
  7. #define BOOST_IOSTREAMS_DETAIL_BUFFERS_HPP_INCLUDED
  8. #if defined(_MSC_VER)
  9. # pragma once
  10. #endif
  11. #include <algorithm> // swap.
  12. #include <memory> // allocator.
  13. #include <boost/config.hpp> // member templates.
  14. #include <boost/iostreams/char_traits.hpp>
  15. #include <boost/iostreams/detail/ios.hpp> // streamsize.
  16. #include <boost/iostreams/read.hpp>
  17. #include <boost/iostreams/traits.hpp> // int_type_of.
  18. #include <boost/iostreams/checked_operations.hpp>
  19. #include <boost/mpl/if.hpp>
  20. #include <boost/type_traits/is_same.hpp>
  21. namespace boost { namespace iostreams { namespace detail {
  22. //----------------Buffers-----------------------------------------------------//
  23. //
  24. // Template name: buffer
  25. // Description: Character buffer.
  26. // Template parameters:
  27. // Ch - The character type.
  28. // Alloc - The Allocator type.
  29. //
  30. template< typename Ch,
  31. typename Alloc = std::allocator<Ch> >
  32. class basic_buffer {
  33. private:
  34. #ifndef BOOST_NO_STD_ALLOCATOR
  35. #if defined(BOOST_NO_CXX11_ALLOCATOR)
  36. typedef typename Alloc::template rebind<Ch>::other allocator_type;
  37. #else
  38. typedef typename std::allocator_traits<Alloc>::template rebind_alloc<Ch> allocator_type;
  39. typedef std::allocator_traits<allocator_type> allocator_traits;
  40. #endif
  41. #else
  42. typedef std::allocator<Ch> allocator_type;
  43. #endif
  44. static Ch* allocate(std::streamsize buffer_size);
  45. public:
  46. basic_buffer();
  47. basic_buffer(std::streamsize buffer_size);
  48. ~basic_buffer();
  49. void resize(std::streamsize buffer_size);
  50. Ch* begin() const { return buf_; }
  51. Ch* end() const { return buf_ + size_; }
  52. Ch* data() const { return buf_; }
  53. std::streamsize size() const { return size_; }
  54. void swap(basic_buffer& rhs);
  55. private:
  56. // Disallow copying and assignment.
  57. basic_buffer(const basic_buffer&);
  58. basic_buffer& operator=(const basic_buffer&);
  59. Ch* buf_;
  60. std::streamsize size_;
  61. };
  62. template<typename Ch, typename Alloc>
  63. void swap(basic_buffer<Ch, Alloc>& lhs, basic_buffer<Ch, Alloc>& rhs)
  64. { lhs.swap(rhs); }
  65. //
  66. // Template name: buffer
  67. // Description: Character buffer with two pointers accessible via ptr() and
  68. // eptr().
  69. // Template parameters:
  70. // Ch - A character type.
  71. //
  72. template< typename Ch,
  73. typename Alloc = std::allocator<Ch> >
  74. class buffer : public basic_buffer<Ch, Alloc> {
  75. private:
  76. typedef basic_buffer<Ch, Alloc> base;
  77. public:
  78. typedef iostreams::char_traits<Ch> traits_type;
  79. using base::resize;
  80. using base::data;
  81. using base::size;
  82. typedef Ch* const const_pointer;
  83. buffer(std::streamsize buffer_size);
  84. Ch* & ptr() { return ptr_; }
  85. const_pointer& ptr() const { return ptr_; }
  86. Ch* & eptr() { return eptr_; }
  87. const_pointer& eptr() const { return eptr_; }
  88. void set(std::streamsize ptr, std::streamsize end);
  89. void swap(buffer& rhs);
  90. // Returns an int_type as a status code.
  91. template<typename Source>
  92. typename int_type_of<Source>::type fill(Source& src)
  93. {
  94. using namespace std;
  95. std::streamsize keep;
  96. if ((keep = static_cast<std::streamsize>(eptr_ - ptr_)) > 0)
  97. traits_type::move(
  98. this->data(),
  99. ptr_,
  100. static_cast<size_t>(keep)
  101. );
  102. set(0, keep);
  103. std::streamsize result =
  104. iostreams::read(src, this->data() + keep, this->size() - keep);
  105. if (result != -1)
  106. this->set(0, keep + result);
  107. return result == -1 ?
  108. traits_type::eof() :
  109. result == 0 ?
  110. traits_type::would_block() :
  111. traits_type::good();
  112. }
  113. // Returns true if one or more characters were written.
  114. template<typename Sink>
  115. bool flush(Sink& dest)
  116. {
  117. using namespace std;
  118. std::streamsize amt = static_cast<std::streamsize>(eptr_ - ptr_);
  119. std::streamsize result = iostreams::write_if(dest, ptr_, amt);
  120. if (result < amt) {
  121. traits_type::move( this->data(),
  122. ptr_ + static_cast<size_t>(result),
  123. static_cast<size_t>(amt - result) );
  124. }
  125. this->set(0, amt - result);
  126. return result != 0;
  127. }
  128. private:
  129. Ch *ptr_, *eptr_;
  130. };
  131. template<typename Ch, typename Alloc>
  132. void swap(buffer<Ch, Alloc>& lhs, buffer<Ch, Alloc>& rhs)
  133. { lhs.swap(rhs); }
  134. //--------------Implementation of basic_buffer--------------------------------//
  135. template<typename Ch, typename Alloc>
  136. basic_buffer<Ch, Alloc>::basic_buffer() : buf_(0), size_(0) { }
  137. template<typename Ch, typename Alloc>
  138. inline Ch* basic_buffer<Ch, Alloc>::allocate(std::streamsize buffer_size)
  139. {
  140. #if defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_STD_ALLOCATOR)
  141. return static_cast<Ch*>(allocator_type().allocate(
  142. static_cast<BOOST_DEDUCED_TYPENAME Alloc::size_type>(buffer_size), 0));
  143. #else
  144. allocator_type alloc;
  145. return static_cast<Ch*>(allocator_traits::allocate(alloc,
  146. static_cast<BOOST_DEDUCED_TYPENAME allocator_traits::size_type>(buffer_size)));
  147. #endif
  148. }
  149. template<typename Ch, typename Alloc>
  150. basic_buffer<Ch, Alloc>::basic_buffer(std::streamsize buffer_size)
  151. : buf_(allocate(buffer_size)),
  152. size_(buffer_size) // Cast for SunPro 5.3.
  153. { }
  154. template<typename Ch, typename Alloc>
  155. inline basic_buffer<Ch, Alloc>::~basic_buffer()
  156. {
  157. if (buf_) {
  158. #if defined(BOOST_NO_CXX11_ALLOCATOR) || defined(BOOST_NO_STD_ALLOCATOR)
  159. allocator_type().deallocate(buf_,
  160. static_cast<BOOST_DEDUCED_TYPENAME Alloc::size_type>(size_));
  161. #else
  162. allocator_type alloc;
  163. allocator_traits::deallocate(alloc, buf_,
  164. static_cast<BOOST_DEDUCED_TYPENAME allocator_traits::size_type>(size_));
  165. #endif
  166. }
  167. }
  168. template<typename Ch, typename Alloc>
  169. inline void basic_buffer<Ch, Alloc>::resize(std::streamsize buffer_size)
  170. {
  171. if (size_ != buffer_size) {
  172. basic_buffer<Ch, Alloc> temp(buffer_size);
  173. std::swap(size_, temp.size_);
  174. std::swap(buf_, temp.buf_);
  175. }
  176. }
  177. template<typename Ch, typename Alloc>
  178. void basic_buffer<Ch, Alloc>::swap(basic_buffer& rhs)
  179. {
  180. std::swap(buf_, rhs.buf_);
  181. std::swap(size_, rhs.size_);
  182. }
  183. //--------------Implementation of buffer--------------------------------------//
  184. template<typename Ch, typename Alloc>
  185. buffer<Ch, Alloc>::buffer(std::streamsize buffer_size)
  186. : basic_buffer<Ch, Alloc>(buffer_size), ptr_(data()), eptr_(data() + buffer_size) { }
  187. template<typename Ch, typename Alloc>
  188. inline void buffer<Ch, Alloc>::set(std::streamsize ptr, std::streamsize end)
  189. {
  190. ptr_ = data() + ptr;
  191. eptr_ = data() + end;
  192. }
  193. template<typename Ch, typename Alloc>
  194. inline void buffer<Ch, Alloc>::swap(buffer& rhs)
  195. {
  196. base::swap(rhs);
  197. std::swap(ptr_, rhs.ptr_);
  198. std::swap(eptr_, rhs.eptr_);
  199. }
  200. //----------------------------------------------------------------------------//
  201. } } } // End namespaces detail, iostreams, boost.
  202. #endif // #ifndef BOOST_IOSTREAMS_DETAIL_BUFFERS_HPP_INCLUDED