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