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