]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // |
2 | // Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) | |
3 | // | |
4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | ||
8 | #ifndef BEAST_STATIC_STREAMBUF_HPP | |
9 | #define BEAST_STATIC_STREAMBUF_HPP | |
10 | ||
11 | #include <beast/config.hpp> | |
12 | #include <boost/utility/base_from_member.hpp> | |
13 | #include <algorithm> | |
14 | #include <array> | |
15 | #include <cstring> | |
16 | ||
17 | namespace beast { | |
18 | ||
19 | /** A @b `DynamicBuffer` with a fixed size internal buffer. | |
20 | ||
21 | Ownership of the underlying storage belongs to the derived class. | |
22 | ||
23 | @note Variables are usually declared using the template class | |
24 | @ref static_streambuf_n; however, to reduce the number of instantiations | |
25 | of template functions receiving static stream buffer arguments in a | |
26 | deduced context, the signature of the receiving function should use | |
27 | @ref static_streambuf. | |
28 | */ | |
29 | class static_streambuf | |
30 | { | |
31 | #if BEAST_DOXYGEN | |
32 | private: | |
33 | #else | |
34 | protected: | |
35 | #endif | |
36 | std::uint8_t* begin_; | |
37 | std::uint8_t* in_; | |
38 | std::uint8_t* out_; | |
39 | std::uint8_t* last_; | |
40 | std::uint8_t* end_; | |
41 | ||
42 | public: | |
43 | #if BEAST_DOXYGEN | |
44 | /// The type used to represent the input sequence as a list of buffers. | |
45 | using const_buffers_type = implementation_defined; | |
46 | ||
47 | /// The type used to represent the output sequence as a list of buffers. | |
48 | using mutable_buffers_type = implementation_defined; | |
49 | ||
50 | #else | |
51 | class const_buffers_type; | |
52 | class mutable_buffers_type; | |
53 | ||
54 | static_streambuf( | |
55 | static_streambuf const& other) noexcept = delete; | |
56 | ||
57 | static_streambuf& operator=( | |
58 | static_streambuf const&) noexcept = delete; | |
59 | ||
60 | #endif | |
61 | ||
62 | /// Return the size of the input sequence. | |
63 | std::size_t | |
64 | size() const | |
65 | { | |
66 | return out_ - in_; | |
67 | } | |
68 | ||
69 | /// Return the maximum sum of the input and output sequence sizes. | |
70 | std::size_t | |
71 | max_size() const | |
72 | { | |
73 | return end_ - begin_; | |
74 | } | |
75 | ||
76 | /// Return the maximum sum of input and output sizes that can be held without an allocation. | |
77 | std::size_t | |
78 | capacity() const | |
79 | { | |
80 | return end_ - in_; | |
81 | } | |
82 | ||
83 | /** Get a list of buffers that represent the input sequence. | |
84 | ||
85 | @note These buffers remain valid across subsequent calls to `prepare`. | |
86 | */ | |
87 | const_buffers_type | |
88 | data() const; | |
89 | ||
90 | /** Get a list of buffers that represent the output sequence, with the given size. | |
91 | ||
92 | @throws std::length_error if the size would exceed the limit | |
93 | imposed by the underlying mutable buffer sequence. | |
94 | ||
95 | @note Buffers representing the input sequence acquired prior to | |
96 | this call remain valid. | |
97 | */ | |
98 | mutable_buffers_type | |
99 | prepare(std::size_t n); | |
100 | ||
101 | /** Move bytes from the output sequence to the input sequence. | |
102 | ||
103 | @note Buffers representing the input sequence acquired prior to | |
104 | this call remain valid. | |
105 | */ | |
106 | void | |
107 | commit(std::size_t n) | |
108 | { | |
109 | out_ += std::min<std::size_t>(n, last_ - out_); | |
110 | } | |
111 | ||
112 | /// Remove bytes from the input sequence. | |
113 | void | |
114 | consume(std::size_t n) | |
115 | { | |
116 | in_ += std::min<std::size_t>(n, out_ - in_); | |
117 | } | |
118 | ||
119 | #if BEAST_DOXYGEN | |
120 | private: | |
121 | #else | |
122 | protected: | |
123 | #endif | |
124 | static_streambuf(std::uint8_t* p, std::size_t n) | |
125 | { | |
126 | reset(p, n); | |
127 | } | |
128 | ||
129 | void | |
130 | reset(std::uint8_t* p, std::size_t n) | |
131 | { | |
132 | begin_ = p; | |
133 | in_ = p; | |
134 | out_ = p; | |
135 | last_ = p; | |
136 | end_ = p + n; | |
137 | } | |
138 | }; | |
139 | ||
140 | //------------------------------------------------------------------------------ | |
141 | ||
142 | /** A `DynamicBuffer` with a fixed size internal buffer. | |
143 | ||
144 | @tparam N The number of bytes in the internal buffer. | |
145 | ||
146 | @note To reduce the number of template instantiations when passing | |
147 | objects of this type in a deduced context, the signature of the | |
148 | receiving function should use `static_streambuf` instead. | |
149 | */ | |
150 | template<std::size_t N> | |
151 | class static_streambuf_n | |
152 | : public static_streambuf | |
153 | #if ! BEAST_DOXYGEN | |
154 | , private boost::base_from_member< | |
155 | std::array<std::uint8_t, N>> | |
156 | #endif | |
157 | { | |
158 | using member_type = boost::base_from_member< | |
159 | std::array<std::uint8_t, N>>; | |
160 | public: | |
161 | #if BEAST_DOXYGEN | |
162 | private: | |
163 | #endif | |
164 | static_streambuf_n( | |
165 | static_streambuf_n const&) = delete; | |
166 | static_streambuf_n& operator=( | |
167 | static_streambuf_n const&) = delete; | |
168 | #if BEAST_DOXYGEN | |
169 | public: | |
170 | #endif | |
171 | ||
172 | /// Construct a static stream buffer. | |
173 | static_streambuf_n() | |
174 | : static_streambuf( | |
175 | member_type::member.data(), | |
176 | member_type::member.size()) | |
177 | { | |
178 | } | |
179 | ||
180 | /** Reset the stream buffer. | |
181 | ||
182 | Postconditions: | |
183 | The input sequence and output sequence are empty, | |
184 | `max_size()` returns `N`. | |
185 | */ | |
186 | void | |
187 | reset() | |
188 | { | |
189 | static_streambuf::reset( | |
190 | member_type::member.data(), | |
191 | member_type::member.size()); | |
192 | } | |
193 | }; | |
194 | ||
195 | } // beast | |
196 | ||
197 | #include <beast/core/impl/static_streambuf.ipp> | |
198 | ||
199 | #endif |