]>
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 | // This is a derivative work based on Zlib, copyright below: | |
8 | /* | |
9 | Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler | |
10 | ||
11 | This software is provided 'as-is', without any express or implied | |
12 | warranty. In no event will the authors be held liable for any damages | |
13 | arising from the use of this software. | |
14 | ||
15 | Permission is granted to anyone to use this software for any purpose, | |
16 | including commercial applications, and to alter it and redistribute it | |
17 | freely, subject to the following restrictions: | |
18 | ||
19 | 1. The origin of this software must not be misrepresented; you must not | |
20 | claim that you wrote the original software. If you use this software | |
21 | in a product, an acknowledgment in the product documentation would be | |
22 | appreciated but is not required. | |
23 | 2. Altered source versions must be plainly marked as such, and must not be | |
24 | misrepresented as being the original software. | |
25 | 3. This notice may not be removed or altered from any source distribution. | |
26 | ||
27 | Jean-loup Gailly Mark Adler | |
28 | jloup@gzip.org madler@alumni.caltech.edu | |
29 | ||
30 | The data format used by the zlib library is described by RFCs (Request for | |
31 | Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 | |
32 | (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). | |
33 | */ | |
34 | ||
35 | #ifndef BEAST_ZLIB_DETAIL_BITSTREAM_HPP | |
36 | #define BEAST_ZLIB_DETAIL_BITSTREAM_HPP | |
37 | ||
38 | #include <boost/assert.hpp> | |
39 | #include <cstdint> | |
40 | #include <iterator> | |
41 | ||
42 | namespace beast { | |
43 | namespace zlib { | |
44 | namespace detail { | |
45 | ||
46 | class bitstream | |
47 | { | |
48 | using value_type = std::uint32_t; | |
49 | ||
50 | value_type v_ = 0; | |
51 | unsigned n_ = 0; | |
52 | ||
53 | public: | |
54 | // returns the number of bits in the reservoir | |
55 | unsigned | |
56 | size() const | |
57 | { | |
58 | return n_; | |
59 | } | |
60 | ||
61 | // discard n bits | |
62 | void | |
63 | drop(std::size_t n) | |
64 | { | |
65 | BOOST_ASSERT(n <= n_); | |
66 | n_ -= static_cast<unsigned>(n); | |
67 | v_ >>= n; | |
68 | } | |
69 | ||
70 | // flush everything | |
71 | void | |
72 | flush() | |
73 | { | |
74 | n_ = 0; | |
75 | v_ = 0; | |
76 | } | |
77 | ||
78 | // flush to the next byte boundary | |
79 | void | |
80 | flush_byte() | |
81 | { | |
82 | drop(n_ % 8); | |
83 | } | |
84 | ||
85 | // ensure at least n bits | |
86 | template<class FwdIt> | |
87 | bool | |
88 | fill(std::size_t n, FwdIt& first, FwdIt const& last); | |
89 | ||
90 | // fill 8 bits, unchecked | |
91 | template<class FwdIt> | |
92 | void | |
93 | fill_8(FwdIt& it); | |
94 | ||
95 | // fill 16 bits, unchecked | |
96 | template<class FwdIt> | |
97 | void | |
98 | fill_16(FwdIt& it); | |
99 | ||
100 | // return n bits | |
101 | template<class Unsigned> | |
102 | void | |
103 | peek(Unsigned& value, std::size_t n); | |
104 | ||
105 | // return everything in the reservoir | |
106 | value_type | |
107 | peek_fast() const | |
108 | { | |
109 | return v_; | |
110 | } | |
111 | ||
112 | // return n bits, and consume | |
113 | template<class Unsigned> | |
114 | void | |
115 | read(Unsigned& value, std::size_t n); | |
116 | ||
117 | // rewind by the number of whole bytes stored (unchecked) | |
118 | template<class BidirIt> | |
119 | void | |
120 | rewind(BidirIt& it); | |
121 | }; | |
122 | ||
123 | template<class FwdIt> | |
124 | inline | |
125 | bool | |
126 | bitstream:: | |
127 | fill(std::size_t n, FwdIt& first, FwdIt const& last) | |
128 | { | |
129 | while(n_ < n) | |
130 | { | |
131 | if(first == last) | |
132 | return false; | |
133 | v_ += static_cast<value_type>(*first++) << n_; | |
134 | n_ += 8; | |
135 | } | |
136 | return true; | |
137 | } | |
138 | ||
139 | template<class FwdIt> | |
140 | inline | |
141 | void | |
142 | bitstream:: | |
143 | fill_8(FwdIt& it) | |
144 | { | |
145 | v_ += static_cast<value_type>(*it++) << n_; | |
146 | n_ += 8; | |
147 | } | |
148 | ||
149 | template<class FwdIt> | |
150 | inline | |
151 | void | |
152 | bitstream:: | |
153 | fill_16(FwdIt& it) | |
154 | { | |
155 | v_ += static_cast<value_type>(*it++) << n_; | |
156 | n_ += 8; | |
157 | v_ += static_cast<value_type>(*it++) << n_; | |
158 | n_ += 8; | |
159 | } | |
160 | ||
161 | template<class Unsigned> | |
162 | inline | |
163 | void | |
164 | bitstream:: | |
165 | peek(Unsigned& value, std::size_t n) | |
166 | { | |
167 | BOOST_ASSERT(n <= sizeof(value)*8); | |
168 | BOOST_ASSERT(n <= n_); | |
169 | value = static_cast<Unsigned>( | |
170 | v_ & ((1ULL << n) - 1)); | |
171 | } | |
172 | ||
173 | template<class Unsigned> | |
174 | inline | |
175 | void | |
176 | bitstream:: | |
177 | read(Unsigned& value, std::size_t n) | |
178 | { | |
179 | BOOST_ASSERT(n < sizeof(v_)*8); | |
180 | BOOST_ASSERT(n <= n_); | |
181 | value = static_cast<Unsigned>( | |
182 | v_ & ((1ULL << n) - 1)); | |
183 | v_ >>= n; | |
184 | n_ -= static_cast<unsigned>(n); | |
185 | } | |
186 | ||
187 | template<class BidirIt> | |
188 | inline | |
189 | void | |
190 | bitstream:: | |
191 | rewind(BidirIt& it) | |
192 | { | |
193 | auto len = n_ >> 3; | |
194 | it = std::prev(it, len); | |
195 | n_ &= 7; | |
196 | v_ &= (1U << n_) - 1; | |
197 | } | |
198 | ||
199 | } // detail | |
200 | } // zlib | |
201 | } // beast | |
202 | ||
203 | #endif |