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