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