]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | typedef typename Alloc::template rebind<Ch>::other allocator_type; | |
43 | #else | |
44 | typedef std::allocator<Ch> allocator_type; | |
45 | #endif | |
46 | public: | |
47 | basic_buffer(); | |
48 | basic_buffer(std::streamsize buffer_size); | |
49 | ~basic_buffer(); | |
50 | void resize(std::streamsize buffer_size); | |
51 | Ch* begin() const { return buf_; } | |
52 | Ch* end() const { return buf_ + size_; } | |
53 | Ch* data() const { return buf_; } | |
54 | std::streamsize size() const { return size_; } | |
55 | void swap(basic_buffer& rhs); | |
56 | private: | |
57 | // Disallow copying and assignment. | |
58 | basic_buffer(const basic_buffer&); | |
59 | basic_buffer& operator=(const basic_buffer&); | |
60 | Ch* buf_; | |
61 | std::streamsize size_; | |
62 | }; | |
63 | ||
64 | template<typename Ch, typename Alloc> | |
65 | void swap(basic_buffer<Ch, Alloc>& lhs, basic_buffer<Ch, Alloc>& rhs) | |
66 | { lhs.swap(rhs); } | |
67 | ||
68 | // | |
69 | // Template name: buffer | |
70 | // Description: Character buffer with two pointers accessible via ptr() and | |
71 | // eptr(). | |
72 | // Template parameters: | |
73 | // Ch - A character type. | |
74 | // | |
75 | template< typename Ch, | |
76 | typename Alloc = std::allocator<Ch> > | |
77 | class buffer : public basic_buffer<Ch, Alloc> { | |
78 | private: | |
79 | typedef basic_buffer<Ch, Alloc> base; | |
80 | public: | |
81 | typedef iostreams::char_traits<Ch> traits_type; | |
82 | using base::resize; | |
83 | using base::data; | |
84 | using base::size; | |
85 | typedef Ch* const const_pointer; | |
86 | buffer(std::streamsize buffer_size); | |
87 | Ch* & ptr() { return ptr_; } | |
88 | const_pointer& ptr() const { return ptr_; } | |
89 | Ch* & eptr() { return eptr_; } | |
90 | const_pointer& eptr() const { return eptr_; } | |
91 | void set(std::streamsize ptr, std::streamsize end); | |
92 | void swap(buffer& rhs); | |
93 | ||
94 | // Returns an int_type as a status code. | |
95 | template<typename Source> | |
96 | typename int_type_of<Source>::type fill(Source& src) | |
97 | { | |
98 | using namespace std; | |
99 | std::streamsize keep; | |
100 | if ((keep = static_cast<std::streamsize>(eptr_ - ptr_)) > 0) | |
101 | traits_type::move( | |
102 | this->data(), | |
103 | ptr_, | |
104 | static_cast<size_t>(keep) | |
105 | ); | |
106 | set(0, keep); | |
107 | std::streamsize result = | |
108 | iostreams::read(src, this->data() + keep, this->size() - keep); | |
109 | if (result != -1) | |
110 | this->set(0, keep + result); | |
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> | |
121 | bool flush(Sink& dest) | |
122 | { | |
123 | using namespace std; | |
124 | std::streamsize amt = static_cast<std::streamsize>(eptr_ - ptr_); | |
125 | std::streamsize result = iostreams::write_if(dest, ptr_, amt); | |
126 | if (result < amt) { | |
127 | traits_type::move( this->data(), | |
128 | ptr_ + static_cast<size_t>(result), | |
129 | static_cast<size_t>(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> | |
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> | |
145 | basic_buffer<Ch, Alloc>::basic_buffer() : buf_(0), size_(0) { } | |
146 | ||
147 | template<typename Ch, typename Alloc> | |
148 | basic_buffer<Ch, Alloc>::basic_buffer(std::streamsize buffer_size) | |
149 | : buf_(static_cast<Ch*>(allocator_type().allocate( | |
150 | static_cast<BOOST_DEDUCED_TYPENAME Alloc::size_type>(buffer_size), 0))), | |
151 | size_(buffer_size) // Cast for SunPro 5.3. | |
152 | { } | |
153 | ||
154 | template<typename Ch, typename Alloc> | |
155 | inline basic_buffer<Ch, Alloc>::~basic_buffer() | |
156 | { | |
157 | if (buf_) { | |
158 | allocator_type().deallocate(buf_, | |
159 | static_cast<BOOST_DEDUCED_TYPENAME Alloc::size_type>(size_)); | |
160 | } | |
161 | } | |
162 | ||
163 | template<typename Ch, typename Alloc> | |
164 | inline void basic_buffer<Ch, Alloc>::resize(std::streamsize buffer_size) | |
165 | { | |
166 | if (size_ != buffer_size) { | |
167 | basic_buffer<Ch, Alloc> temp(buffer_size); | |
168 | std::swap(size_, temp.size_); | |
169 | std::swap(buf_, temp.buf_); | |
170 | } | |
171 | } | |
172 | ||
173 | template<typename Ch, typename Alloc> | |
174 | void basic_buffer<Ch, Alloc>::swap(basic_buffer& rhs) | |
175 | { | |
176 | std::swap(buf_, rhs.buf_); | |
177 | std::swap(size_, rhs.size_); | |
178 | } | |
179 | ||
180 | //--------------Implementation of buffer--------------------------------------// | |
181 | ||
182 | template<typename Ch, typename Alloc> | |
183 | buffer<Ch, Alloc>::buffer(std::streamsize buffer_size) | |
184 | : basic_buffer<Ch, Alloc>(buffer_size) { } | |
185 | ||
186 | template<typename Ch, typename Alloc> | |
187 | inline void buffer<Ch, Alloc>::set(std::streamsize ptr, std::streamsize end) | |
188 | { | |
189 | ptr_ = data() + ptr; | |
190 | eptr_ = data() + end; | |
191 | } | |
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 | //----------------------------------------------------------------------------// | |
202 | ||
203 | } } } // End namespaces detail, iostreams, boost. | |
204 | ||
205 | #endif // #ifndef BOOST_IOSTREAMS_DETAIL_BUFFERS_HPP_INCLUDED |