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
26namespace 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//
37template< typename Ch,
38 typename Alloc = std::allocator<Ch> >
39class basic_buffer {
40private:
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);
52public:
53 basic_buffer();
54 basic_buffer(std::streamsize buffer_size);
55 ~basic_buffer();
56 void resize(std::streamsize buffer_size);
57 Ch* begin() const { return buf_; }
58 Ch* end() const { return buf_ + size_; }
59 Ch* data() const { return buf_; }
60 std::streamsize size() const { return size_; }
61 void swap(basic_buffer& rhs);
62private:
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
70template<typename Ch, typename Alloc>
71void 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//
81template< typename Ch,
82 typename Alloc = std::allocator<Ch> >
83class buffer : public basic_buffer<Ch, Alloc> {
84private:
85 typedef basic_buffer<Ch, Alloc> base;
86public:
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);
93 Ch* & ptr() { return ptr_; }
94 const_pointer& ptr() const { return ptr_; }
95 Ch* & eptr() { return eptr_; }
96 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>
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(ptr: 0, end: keep);
113 std::streamsize result =
114 iostreams::read(src, this->data() + keep, this->size() - keep);
115 if (result != -1)
116 this->set(ptr: 0, end: 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>
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(ptr: 0, end: amt - result);
138 return result != 0;
139 }
140private:
141 Ch *ptr_, *eptr_;
142};
143
144template<typename Ch, typename Alloc>
145void swap(buffer<Ch, Alloc>& lhs, buffer<Ch, Alloc>& rhs)
146{ lhs.swap(rhs); }
147
148//--------------Implementation of basic_buffer--------------------------------//
149
150template<typename Ch, typename Alloc>
151basic_buffer<Ch, Alloc>::basic_buffer() : buf_(0), size_(0) { }
152
153template<typename Ch, typename Alloc>
154inline 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
166template<typename Ch, typename Alloc>
167basic_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
172template<typename Ch, typename Alloc>
173inline 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
187template<typename Ch, typename Alloc>
188inline 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(a&: size_, b&: temp.size_);
193 std::swap(buf_, temp.buf_);
194 }
195}
196
197template<typename Ch, typename Alloc>
198void basic_buffer<Ch, Alloc>::swap(basic_buffer& rhs)
199{
200 std::swap(buf_, rhs.buf_);
201 std::swap(a&: size_, b&: rhs.size_);
202}
203
204//--------------Implementation of buffer--------------------------------------//
205
206template<typename Ch, typename Alloc>
207buffer<Ch, Alloc>::buffer(std::streamsize buffer_size)
208 : basic_buffer<Ch, Alloc>(buffer_size), ptr_(data()), eptr_(data() + buffer_size) { }
209
210template<typename Ch, typename Alloc>
211inline void buffer<Ch, Alloc>::set(std::streamsize ptr, std::streamsize end)
212{
213 ptr_ = data() + ptr;
214 eptr_ = data() + end;
215}
216
217template<typename Ch, typename Alloc>
218inline 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

source code of boost/libs/iostreams/include/boost/iostreams/detail/buffer.hpp