?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/beast.zip
???????
PK OP�[�*��G G zlib.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_ZLIB_HPP #define BOOST_BEAST_ZLIB_HPP #include <boost/beast/core/detail/config.hpp> #include <boost/beast/zlib/deflate_stream.hpp> #include <boost/beast/zlib/error.hpp> #include <boost/beast/zlib/inflate_stream.hpp> #include <boost/beast/zlib/zlib.hpp> #endif PK OP�[h��z z core.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_CORE_HPP #define BOOST_BEAST_CORE_HPP #include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/async_base.hpp> #include <boost/beast/core/basic_stream.hpp> #include <boost/beast/core/bind_handler.hpp> #include <boost/beast/core/buffer_traits.hpp> #include <boost/beast/core/buffered_read_stream.hpp> #include <boost/beast/core/buffers_adaptor.hpp> #include <boost/beast/core/buffers_cat.hpp> #include <boost/beast/core/buffers_prefix.hpp> #include <boost/beast/core/buffers_range.hpp> #include <boost/beast/core/buffers_suffix.hpp> #include <boost/beast/core/buffers_to_string.hpp> #include <boost/beast/core/detect_ssl.hpp> #include <boost/beast/core/error.hpp> #include <boost/beast/core/file.hpp> #include <boost/beast/core/file_base.hpp> #include <boost/beast/core/file_posix.hpp> #include <boost/beast/core/file_stdio.hpp> #include <boost/beast/core/file_win32.hpp> #include <boost/beast/core/flat_buffer.hpp> #include <boost/beast/core/flat_static_buffer.hpp> #include <boost/beast/core/flat_stream.hpp> #include <boost/beast/core/make_printable.hpp> #include <boost/beast/core/multi_buffer.hpp> #include <boost/beast/core/ostream.hpp> #include <boost/beast/core/rate_policy.hpp> #include <boost/beast/core/read_size.hpp> #include <boost/beast/core/role.hpp> #include <boost/beast/core/saved_handler.hpp> #include <boost/beast/core/span.hpp> #include <boost/beast/core/static_buffer.hpp> #include <boost/beast/core/static_string.hpp> #include <boost/beast/core/stream_traits.hpp> #include <boost/beast/core/string.hpp> #include <boost/beast/core/tcp_stream.hpp> #endif PK OP�[�[�� � zlib/zlib.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_ZLIB_HPP #define BOOST_BEAST_ZLIB_ZLIB_HPP #include <boost/beast/core/detail/config.hpp> #include <cstdint> #include <cstdlib> namespace boost { namespace beast { namespace zlib { #if !defined(__MACTYPES__) using Byte = unsigned char; // 8 bits #endif using uInt = unsigned int; // 16 bits or more /* Possible values of the data_type field (though see inflate()) */ enum kind { binary = 0, text = 1, unknown = 2 }; /** Deflate codec parameters. Objects of this type are filled in by callers and provided to the deflate codec to define the input and output areas for the next compress or decompress operation. The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use in the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ struct z_params { /** A pointer to the next input byte. If there is no more input, this may be set to `nullptr`. */ void const* next_in; /** The number of bytes of input available at `next_in`. If there is no more input, this should be set to zero. */ std::size_t avail_in; /** The total number of input bytes read so far. */ std::size_t total_in = 0; /** A pointer to the next output byte. */ void* next_out; /** The remaining bytes of space at `next_out`. */ std::size_t avail_out; /** The total number of bytes output so far. */ std::size_t total_out = 0; int data_type = unknown; // best guess about the data type: binary or text }; /** Flush option. */ enum class Flush { // order matters none, block, partial, sync, full, finish, trees }; /* compression levels */ enum compression { none = 0, best_speed = 1, best_size = 9, default_size = -1 }; /** Compression strategy. These are used when compressing streams. */ enum class Strategy { /** Default strategy. This is suitable for general purpose compression, and works well in the majority of cases. */ normal, /** Filtered strategy. This strategy should be used when the data be compressed is produced by a filter or predictor. */ filtered, /** Huffman-only strategy. This strategy only performs Huffman encoding, without doing any string matching. */ huffman, /** Run Length Encoding strategy. This strategy limits match distances to one, making it equivalent to run length encoding. This can give better performance for things like PNG image data. */ rle, /** Fixed table strategy. This strategy prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. */ fixed }; } // zlib } // beast } // boost #endif PK OP�[��W� � zlib/impl/error.ippnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_IMPL_ERROR_IPP #define BOOST_BEAST_ZLIB_IMPL_ERROR_IPP #include <boost/beast/zlib/error.hpp> #include <type_traits> namespace boost { namespace beast { namespace zlib { namespace detail { class error_codes : public error_category { public: const char* name() const noexcept override { return "boost.beast.zlib"; } std::string message(int ev) const override { switch(static_cast<error>(ev)) { case error::need_buffers: return "need buffers"; case error::end_of_stream: return "unexpected end of deflate stream"; case error::need_dict: return "need dict"; case error::stream_error: return "stream error"; case error::invalid_block_type: return "invalid block type"; case error::invalid_stored_length: return "invalid stored block length"; case error::too_many_symbols: return "too many symbols"; case error::invalid_code_lengths: return "invalid code lengths"; case error::invalid_bit_length_repeat: return "invalid bit length repeat"; case error::missing_eob: return "missing end of block code"; case error::invalid_literal_length: return "invalid literal/length code"; case error::invalid_distance_code: return "invalid distance code"; case error::invalid_distance: return "invalid distance"; case error::over_subscribed_length: return "over-subscribed length"; case error::incomplete_length_set: return "incomplete length set"; case error::general: default: return "beast.zlib error"; } } error_condition default_error_condition(int ev) const noexcept override { return error_condition{ev, *this}; } bool equivalent(int ev, error_condition const& condition ) const noexcept override { return condition.value() == ev && &condition.category() == this; } bool equivalent(error_code const& error, int ev) const noexcept override { return error.value() == ev && &error.category() == this; } }; } // detail error_code make_error_code(error ev) { static detail::error_codes const cat{}; return error_code{static_cast< std::underlying_type<error>::type>(ev), cat}; } } // zlib } // beast } // boost #endif PK OP�[��� � zlib/impl/error.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_IMPL_ERROR_HPP #define BOOST_BEAST_ZLIB_IMPL_ERROR_HPP namespace boost { namespace system { template<> struct is_error_code_enum<::boost::beast::zlib::error> { static bool const value = true; }; } // system } // boost namespace boost { namespace beast { namespace zlib { BOOST_BEAST_DECL error_code make_error_code(error ev); } // zlib } // beast } // boost #endif PK OP�[q�V� zlib/error.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_ERROR_HPP #define BOOST_BEAST_ZLIB_ERROR_HPP #include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/error.hpp> namespace boost { namespace beast { namespace zlib { /** Error codes returned by the deflate codecs. */ enum class error { /** Additional buffers are required. This error indicates that one or both of the buffers provided buffers do not have sufficient available bytes to make forward progress. This does not always indicate a failure condition. @note This is the same as `Z_BUF_ERROR` returned by ZLib. */ need_buffers = 1, /** End of stream reached. @note This is the same as `Z_STREAM_END` returned by ZLib. */ end_of_stream, /** Preset dictionary required This error indicates that a preset dictionary was not provided and is now needed at this point. This does not always indicate a failure condition. @note This is the same as `Z_NEED_DICT` returned by ZLib. */ need_dict, /** Invalid stream or parameters. This error is returned when invalid parameters are passed, or the operation being performed is not consistent with the state of the stream. For example, attempting to write data when the end of stream is already reached. @note This is the same as `Z_STREAM_ERROR` returned by ZLib. */ stream_error, // // Errors generated by basic_deflate_stream // // // Errors generated by basic_inflate_stream // /// Invalid block type invalid_block_type, /// Invalid stored block length invalid_stored_length, /// Too many length or distance symbols too_many_symbols, /// Invalid code lengths invalid_code_lengths, /// Invalid bit length repeat invalid_bit_length_repeat, /// Missing end of block code missing_eob, /// Invalid literal/length code invalid_literal_length, /// Invalid distance code invalid_distance_code, /// Invalid distance too far back invalid_distance, // // Errors generated by inflate_table // /// Over-subscribed length code over_subscribed_length, /// Incomplete length set incomplete_length_set, /// general error general }; } // zlib } // beast } // boost #include <boost/beast/zlib/impl/error.hpp> #ifdef BOOST_BEAST_HEADER_ONLY #include <boost/beast/zlib/impl/error.ipp> #endif #endif PK OP�[��.� .� zlib/detail/inflate_stream.ippnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_DETAIL_INFLATE_STREAM_IPP #define BOOST_BEAST_ZLIB_DETAIL_INFLATE_STREAM_IPP #include <boost/beast/zlib/detail/inflate_stream.hpp> #include <boost/throw_exception.hpp> #include <array> namespace boost { namespace beast { namespace zlib { namespace detail { void inflate_stream:: doClear() { } void inflate_stream:: doReset(int windowBits) { if(windowBits < 8 || windowBits > 15) BOOST_THROW_EXCEPTION(std::domain_error{ "windowBits out of range"}); w_.reset(windowBits); bi_.flush(); mode_ = HEAD; last_ = 0; dmax_ = 32768U; lencode_ = codes_; distcode_ = codes_; next_ = codes_; back_ = -1; } void inflate_stream:: doWrite(z_params& zs, Flush flush, error_code& ec) { ranges r; r.in.first = static_cast< std::uint8_t const*>(zs.next_in); r.in.last = r.in.first + zs.avail_in; r.in.next = r.in.first; r.out.first = static_cast< std::uint8_t*>(zs.next_out); r.out.last = r.out.first + zs.avail_out; r.out.next = r.out.first; auto const done = [&] { /* Return from inflate(), updating the total counts and the check value. If there was no progress during the inflate() call, return a buffer error. Call updatewindow() to create and/or update the window state. Note: a memory error from inflate() is non-recoverable. */ // VFALCO TODO Don't allocate update the window unless necessary if(/*wsize_ ||*/ (r.out.used() && mode_ < BAD && (mode_ < CHECK || flush != Flush::finish))) w_.write(r.out.first, r.out.used()); zs.next_in = r.in.next; zs.avail_in = r.in.avail(); zs.next_out = r.out.next; zs.avail_out = r.out.avail(); zs.total_in += r.in.used(); zs.total_out += r.out.used(); zs.data_type = bi_.size() + (last_ ? 64 : 0) + (mode_ == TYPE ? 128 : 0) + (mode_ == LEN_ || mode_ == COPY_ ? 256 : 0); if(((! r.in.used() && ! r.out.used()) || flush == Flush::finish) && ! ec) ec = error::need_buffers; }; auto const err = [&](error e) { ec = e; mode_ = BAD; }; if(mode_ == TYPE) mode_ = TYPEDO; for(;;) { switch(mode_) { case HEAD: mode_ = TYPEDO; break; case TYPE: if(flush == Flush::block || flush == Flush::trees) return done(); // fall through case TYPEDO: { if(last_) { bi_.flush_byte(); mode_ = CHECK; break; } if(! bi_.fill(3, r.in.next, r.in.last)) return done(); std::uint8_t v; bi_.read(v, 1); last_ = v != 0; bi_.read(v, 2); switch(v) { case 0: // uncompressed block mode_ = STORED; break; case 1: // fixed Huffman table fixedTables(); mode_ = LEN_; /* decode codes */ if(flush == Flush::trees) return done(); break; case 2: // dynamic Huffman table mode_ = TABLE; break; default: return err(error::invalid_block_type); } break; } case STORED: { bi_.flush_byte(); std::uint32_t v; if(! bi_.fill(32, r.in.next, r.in.last)) return done(); bi_.peek(v, 32); length_ = v & 0xffff; if(length_ != ((v >> 16) ^ 0xffff)) return err(error::invalid_stored_length); // flush instead of read, otherwise // undefined right shift behavior. bi_.flush(); mode_ = COPY_; if(flush == Flush::trees) return done(); BOOST_FALLTHROUGH; } case COPY_: mode_ = COPY; BOOST_FALLTHROUGH; case COPY: { auto copy = length_; if(copy == 0) { mode_ = TYPE; break; } copy = clamp(copy, r.in.avail()); copy = clamp(copy, r.out.avail()); if(copy == 0) return done(); std::memcpy(r.out.next, r.in.next, copy); r.in.next += copy; r.out.next += copy; length_ -= copy; break; } case TABLE: if(! bi_.fill(5 + 5 + 4, r.in.next, r.in.last)) return done(); bi_.read(nlen_, 5); nlen_ += 257; bi_.read(ndist_, 5); ndist_ += 1; bi_.read(ncode_, 4); ncode_ += 4; if(nlen_ > 286 || ndist_ > 30) return err(error::too_many_symbols); have_ = 0; mode_ = LENLENS; BOOST_FALLTHROUGH; case LENLENS: { static std::array<std::uint8_t, 19> constexpr order = {{ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}}; while(have_ < ncode_) { if(! bi_.fill(3, r.in.next, r.in.last)) return done(); bi_.read(lens_[order[have_]], 3); ++have_; } while(have_ < order.size()) lens_[order[have_++]] = 0; next_ = &codes_[0]; lencode_ = next_; lenbits_ = 7; inflate_table(build::codes, &lens_[0], order.size(), &next_, &lenbits_, work_, ec); if(ec) { mode_ = BAD; break; } have_ = 0; mode_ = CODELENS; BOOST_FALLTHROUGH; } case CODELENS: { while(have_ < nlen_ + ndist_) { std::uint16_t v; if(! bi_.fill(lenbits_, r.in.next, r.in.last)) return done(); bi_.peek(v, lenbits_); auto cp = &lencode_[v]; if(cp->val < 16) { bi_.drop(cp->bits); lens_[have_++] = cp->val; } else { std::uint16_t len; std::uint16_t copy; if(cp->val == 16) { if(! bi_.fill(cp->bits + 2, r.in.next, r.in.last)) return done(); bi_.drop(cp->bits); if(have_ == 0) return err(error::invalid_bit_length_repeat); bi_.read(copy, 2); len = lens_[have_ - 1]; copy += 3; } else if(cp->val == 17) { if(! bi_.fill(cp->bits + 3, r.in.next, r.in.last)) return done(); bi_.drop(cp->bits); bi_.read(copy, 3); len = 0; copy += 3; } else { if(! bi_.fill(cp->bits + 7, r.in.next, r.in.last)) return done(); bi_.drop(cp->bits); bi_.read(copy, 7); len = 0; copy += 11; } if(have_ + copy > nlen_ + ndist_) return err(error::invalid_bit_length_repeat); std::fill(&lens_[have_], &lens_[have_ + copy], len); have_ += copy; copy = 0; } } // handle error breaks in while if(mode_ == BAD) break; // check for end-of-block code (better have one) if(lens_[256] == 0) return err(error::missing_eob); /* build code tables -- note: do not change the lenbits or distbits values here (9 and 6) without reading the comments in inftrees.hpp concerning the kEnough constants, which depend on those values */ next_ = &codes_[0]; lencode_ = next_; lenbits_ = 9; inflate_table(build::lens, &lens_[0], nlen_, &next_, &lenbits_, work_, ec); if(ec) { mode_ = BAD; return; } distcode_ = next_; distbits_ = 6; inflate_table(build::dists, lens_ + nlen_, ndist_, &next_, &distbits_, work_, ec); if(ec) { mode_ = BAD; return; } mode_ = LEN_; if(flush == Flush::trees) return done(); BOOST_FALLTHROUGH; } case LEN_: mode_ = LEN; BOOST_FALLTHROUGH; case LEN: { if(r.in.avail() >= 6 && r.out.avail() >= 258) { inflate_fast(r, ec); if(ec) { mode_ = BAD; return; } if(mode_ == TYPE) back_ = -1; break; } if(! bi_.fill(lenbits_, r.in.next, r.in.last)) return done(); std::uint16_t v; back_ = 0; bi_.peek(v, lenbits_); auto cp = &lencode_[v]; if(cp->op && (cp->op & 0xf0) == 0) { auto prev = cp; if(! bi_.fill(prev->bits + prev->op, r.in.next, r.in.last)) return done(); bi_.peek(v, prev->bits + prev->op); cp = &lencode_[prev->val + (v >> prev->bits)]; bi_.drop(prev->bits + cp->bits); back_ += prev->bits + cp->bits; } else { bi_.drop(cp->bits); back_ += cp->bits; } length_ = cp->val; if(cp->op == 0) { mode_ = LIT; break; } if(cp->op & 32) { back_ = -1; mode_ = TYPE; break; } if(cp->op & 64) return err(error::invalid_literal_length); extra_ = cp->op & 15; mode_ = LENEXT; BOOST_FALLTHROUGH; } case LENEXT: if(extra_) { if(! bi_.fill(extra_, r.in.next, r.in.last)) return done(); std::uint16_t v; bi_.read(v, extra_); length_ += v; back_ += extra_; } was_ = length_; mode_ = DIST; BOOST_FALLTHROUGH; case DIST: { if(! bi_.fill(distbits_, r.in.next, r.in.last)) return done(); std::uint16_t v; bi_.peek(v, distbits_); auto cp = &distcode_[v]; if((cp->op & 0xf0) == 0) { auto prev = cp; if(! bi_.fill(prev->bits + prev->op, r.in.next, r.in.last)) return done(); bi_.peek(v, prev->bits + prev->op); cp = &distcode_[prev->val + (v >> prev->bits)]; bi_.drop(prev->bits + cp->bits); back_ += prev->bits + cp->bits; } else { bi_.drop(cp->bits); back_ += cp->bits; } if(cp->op & 64) return err(error::invalid_distance_code); offset_ = cp->val; extra_ = cp->op & 15; mode_ = DISTEXT; BOOST_FALLTHROUGH; } case DISTEXT: if(extra_) { std::uint16_t v; if(! bi_.fill(extra_, r.in.next, r.in.last)) return done(); bi_.read(v, extra_); offset_ += v; back_ += extra_; } #ifdef INFLATE_STRICT if(offset_ > dmax_) return err(error::invalid_distance); #endif mode_ = MATCH; BOOST_FALLTHROUGH; case MATCH: { if(! r.out.avail()) return done(); if(offset_ > r.out.used()) { // copy from window auto offset = static_cast<std::uint16_t>( offset_ - r.out.used()); if(offset > w_.size()) return err(error::invalid_distance); auto const n = clamp(clamp( length_, offset), r.out.avail()); w_.read(r.out.next, offset, n); r.out.next += n; length_ -= n; } else { // copy from output auto in = r.out.next - offset_; auto n = clamp(length_, r.out.avail()); length_ -= n; while(n--) *r.out.next++ = *in++; } if(length_ == 0) mode_ = LEN; break; } case LIT: { if(! r.out.avail()) return done(); auto const v = static_cast<std::uint8_t>(length_); *r.out.next++ = v; mode_ = LEN; break; } case CHECK: mode_ = DONE; BOOST_FALLTHROUGH; case DONE: ec = error::end_of_stream; return done(); case BAD: return done(); case SYNC: default: BOOST_THROW_EXCEPTION(std::logic_error{ "stream error"}); } } } //------------------------------------------------------------------------------ /* Build a set of tables to decode the provided canonical Huffman code. The code lengths are lens[0..codes-1]. The result starts at *table, whose indices are 0..2^bits-1. work is a writable array of at least lens shorts, which is used as a work area. type is the type of code to be generated, build::codes, build::lens, or build::dists. On return, zero is success, -1 is an invalid code, and +1 means that kEnough isn't enough. table on return points to the next available entry's address. bits is the requested root table index bits, and on return it is the actual root table index bits. It will differ if the request is greater than the longest code or if it is less than the shortest code. */ void inflate_stream:: inflate_table( build type, std::uint16_t* lens, std::size_t codes, code** table, unsigned *bits, std::uint16_t* work, error_code& ec) { unsigned len; // a code's length in bits unsigned sym; // index of code symbols unsigned min, max; // minimum and maximum code lengths unsigned root; // number of index bits for root table unsigned curr; // number of index bits for current table unsigned drop; // code bits to drop for sub-table int left; // number of prefix codes available unsigned used; // code entries in table used unsigned huff; // Huffman code unsigned incr; // for incrementing code, index unsigned fill; // index for replicating entries unsigned low; // low bits for current root entry unsigned mask; // mask for low root bits code here; // table entry for duplication code *next; // next available space in table std::uint16_t const* base; // base value table to use std::uint16_t const* extra; // extra bits table to use int end; // use base and extra for symbol > end std::uint16_t count[15+1]; // number of codes of each length std::uint16_t offs[15+1]; // offsets in table for each length // Length codes 257..285 base static std::uint16_t constexpr lbase[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; // Length codes 257..285 extra static std::uint16_t constexpr lext[31] = { 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78}; // Distance codes 0..29 base static std::uint16_t constexpr dbase[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0}; // Distance codes 0..29 extra static std::uint16_t constexpr dext[32] = { 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 64, 64}; /* Process a set of code lengths to create a canonical Huffman code. The code lengths are lens[0..codes-1]. Each length corresponds to the symbols 0..codes-1. The Huffman code is generated by first sorting the symbols by length from short to long, and retaining the symbol order for codes with equal lengths. Then the code starts with all zero bits for the first code of the shortest length, and the codes are integer increments for the same length, and zeros are appended as the length increases. For the deflate format, these bits are stored backwards from their more natural integer increment ordering, and so when the decoding tables are built in the large loop below, the integer codes are incremented backwards. This routine assumes, but does not check, that all of the entries in lens[] are in the range 0..15. The caller must assure this. 1..15 is interpreted as that code length. zero means that that symbol does not occur in this code. The codes are sorted by computing a count of codes for each length, creating from that a table of starting indices for each length in the sorted table, and then entering the symbols in order in the sorted table. The sorted table is work[], with that space being provided by the caller. The length counts are used for other purposes as well, i.e. finding the minimum and maximum length codes, determining if there are any codes at all, checking for a valid set of lengths, and looking ahead at length counts to determine sub-table sizes when building the decoding tables. */ /* accumulate lengths for codes (assumes lens[] all in 0..15) */ for (len = 0; len <= 15; len++) count[len] = 0; for (sym = 0; sym < codes; sym++) count[lens[sym]]++; /* bound code lengths, force root to be within code lengths */ root = *bits; for (max = 15; max >= 1; max--) if (count[max] != 0) break; if (root > max) root = max; if (max == 0) { /* no symbols to code at all */ here.op = (std::uint8_t)64; /* invalid code marker */ here.bits = (std::uint8_t)1; here.val = (std::uint16_t)0; *(*table)++ = here; /* make a table to force an error */ *(*table)++ = here; *bits = 1; return; /* no symbols, but wait for decoding to report error */ } for (min = 1; min < max; min++) if (count[min] != 0) break; if (root < min) root = min; /* check for an over-subscribed or incomplete set of lengths */ left = 1; for (len = 1; len <= 15; len++) { left <<= 1; left -= count[len]; if (left < 0) { ec = error::over_subscribed_length; return; } } if (left > 0 && (type == build::codes || max != 1)) { ec = error::incomplete_length_set; return; } /* generate offsets into symbol table for each length for sorting */ offs[1] = 0; for (len = 1; len < 15; len++) offs[len + 1] = offs[len] + count[len]; /* sort symbols by length, by symbol order within each length */ for (sym = 0; sym < codes; sym++) if (lens[sym] != 0) work[offs[lens[sym]]++] = (std::uint16_t)sym; /* Create and fill in decoding tables. In this loop, the table being filled is at next and has curr index bits. The code being used is huff with length len. That code is converted to an index by dropping drop bits off of the bottom. For codes where len is less than drop + curr, those top drop + curr - len bits are incremented through all values to fill the table with replicated entries. root is the number of index bits for the root table. When len exceeds root, sub-tables are created pointed to by the root entry with an index of the low root bits of huff. This is saved in low to check for when a new sub-table should be started. drop is zero when the root table is being filled, and drop is root when sub-tables are being filled. When a new sub-table is needed, it is necessary to look ahead in the code lengths to determine what size sub-table is needed. The length counts are used for this, and so count[] is decremented as codes are entered in the tables. used keeps track of how many table entries have been allocated from the provided *table space. It is checked for build::lens and DIST tables against the constants kEnoughLens and kEnoughDists to guard against changes in the initial root table size constants. See the comments in inftrees.hpp for more information. sym increments through all symbols, and the loop terminates when all codes of length max, i.e. all codes, have been processed. This routine permits incomplete codes, so another loop after this one fills in the rest of the decoding tables with invalid code markers. */ /* set up for code type */ switch (type) { case build::codes: base = extra = work; /* dummy value--not used */ end = 19; break; case build::lens: base = lbase; base -= 257; extra = lext; extra -= 257; end = 256; break; default: /* build::dists */ base = dbase; extra = dext; end = -1; } /* initialize state for loop */ huff = 0; /* starting code */ sym = 0; /* starting code symbol */ len = min; /* starting code length */ next = *table; /* current table to fill in */ curr = root; /* current table index bits */ drop = 0; /* current bits to drop from code for index */ low = (unsigned)(-1); /* trigger new sub-table when len > root */ used = 1U << root; /* use root table entries */ mask = used - 1; /* mask for comparing low */ auto const not_enough = [] { BOOST_THROW_EXCEPTION(std::logic_error{ "insufficient output size when inflating tables"}); }; // check available table space if ((type == build::lens && used > kEnoughLens) || (type == build::dists && used > kEnoughDists)) return not_enough(); /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (std::uint8_t)(len - drop); if ((int)(work[sym]) < end) { here.op = (std::uint8_t)0; here.val = work[sym]; } else if ((int)(work[sym]) > end) { here.op = (std::uint8_t)(extra[work[sym]]); here.val = base[work[sym]]; } else { here.op = (std::uint8_t)(32 + 64); /* end of block */ here.val = 0; } /* replicate for those indices with low len bits equal to huff */ incr = 1U << (len - drop); fill = 1U << curr; min = fill; /* save offset to next table */ do { fill -= incr; next[(huff >> drop) + fill] = here; } while (fill != 0); /* backwards increment the len-bit code huff */ incr = 1U << (len - 1); while (huff & incr) incr >>= 1; if (incr != 0) { huff &= incr - 1; huff += incr; } else huff = 0; /* go to next symbol, update count, len */ sym++; if (--(count[len]) == 0) { if (len == max) break; len = lens[work[sym]]; } /* create new sub-table if needed */ if (len > root && (huff & mask) != low) { /* if first time, transition to sub-tables */ if (drop == 0) drop = root; /* increment past last table */ next += min; /* here min is 1 << curr */ /* determine length of next table */ curr = len - drop; left = (int)(1 << curr); while (curr + drop < max) { left -= count[curr + drop]; if (left <= 0) break; curr++; left <<= 1; } /* check for enough space */ used += 1U << curr; if ((type == build::lens && used > kEnoughLens) || (type == build::dists && used > kEnoughDists)) return not_enough(); /* point entry in root table to sub-table */ low = huff & mask; (*table)[low].op = (std::uint8_t)curr; (*table)[low].bits = (std::uint8_t)root; (*table)[low].val = (std::uint16_t)(next - *table); } } /* fill in remaining table entry if code is incomplete (guaranteed to have at most one remaining entry, since if the code is incomplete, the maximum code length that was allowed to get this far is one bit) */ if (huff != 0) { here.op = 64; // invalid code marker here.bits = (std::uint8_t)(len - drop); here.val = 0; next[huff] = here; } *table += used; *bits = root; } auto inflate_stream:: get_fixed_tables() -> codes const& { struct fixed_codes : codes { code len_[512]; code dist_[32]; fixed_codes() { lencode = len_; lenbits = 9; distcode = dist_; distbits = 5; std::uint16_t lens[320]; std::uint16_t work[288]; std::fill(&lens[ 0], &lens[144], std::uint16_t{8}); std::fill(&lens[144], &lens[256], std::uint16_t{9}); std::fill(&lens[256], &lens[280], std::uint16_t{7}); std::fill(&lens[280], &lens[288], std::uint16_t{8}); { error_code ec; auto next = &len_[0]; inflate_table(build::lens, lens, 288, &next, &lenbits, work, ec); if(ec) BOOST_THROW_EXCEPTION(std::logic_error{ec.message()}); } // VFALCO These fixups are from ZLib len_[ 99].op = 64; len_[227].op = 64; len_[355].op = 64; len_[483].op = 64; { error_code ec; auto next = &dist_[0]; std::fill(&lens[0], &lens[32], std::uint16_t{5}); inflate_table(build::dists, lens, 32, &next, &distbits, work, ec); if(ec) BOOST_THROW_EXCEPTION(std::logic_error{ec.message()}); } } }; static fixed_codes const fc; return fc; } void inflate_stream:: fixedTables() { auto const fc = get_fixed_tables(); lencode_ = fc.lencode; lenbits_ = fc.lenbits; distcode_ = fc.distcode; distbits_ = fc.distbits; } /* Decode literal, length, and distance codes and write out the resulting literal and match bytes until either not enough input or output is available, an end-of-block is encountered, or a data error is encountered. When large enough input and output buffers are supplied to inflate(), for example, a 16K input buffer and a 64K output buffer, more than 95% of the inflate execution time is spent in this routine. Entry assumptions: state->mode_ == LEN zs.avail_in >= 6 zs.avail_out >= 258 start >= zs.avail_out state->bits_ < 8 On return, state->mode_ is one of: LEN -- ran out of enough output space or enough available input TYPE -- reached end of block code, inflate() to interpret next block BAD -- error in block data Notes: - The maximum input bits used by a length/distance pair is 15 bits for the length code, 5 bits for the length extra, 15 bits for the distance code, and 13 bits for the distance extra. This totals 48 bits, or six bytes. Therefore if zs.avail_in >= 6, then there is enough input to avoid checking for available input while decoding. - The maximum bytes that a single length/distance pair can output is 258 bytes, which is the maximum length that can be coded. inflate_fast() requires zs.avail_out >= 258 for each loop to avoid checking for output space. inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - Using bit fields for code structure - Different op definition to avoid & for extra bits (do & for table bits) - Three separate decoding do-loops for direct, window, and wnext == 0 - Special case for distance > 1 copies to do overlapped load and store copy - Explicit branch predictions (based on measured branch probabilities) - Deferring match copy and interspersed it with decoding subsequent codes - Swapping literal/length else - Swapping window/direct else - Larger unrolled copy loops (three is about right) - Moving len -= 3 statement into middle of loop */ void inflate_stream:: inflate_fast(ranges& r, error_code& ec) { unsigned char const* last; // have enough input while in < last unsigned char *end; // while out < end, enough space available std::size_t op; // code bits, operation, extra bits, or window position, window bytes to copy unsigned len; // match length, unused bytes unsigned dist; // match distance unsigned const lmask = (1U << lenbits_) - 1; // mask for first level of length codes unsigned const dmask = (1U << distbits_) - 1; // mask for first level of distance codes last = r.in.next + (r.in.avail() - 5); end = r.out.next + (r.out.avail() - 257); /* decode literals and length/distances until end-of-block or not enough input data or output space */ do { if(bi_.size() < 15) bi_.fill_16(r.in.next); auto cp = &lencode_[bi_.peek_fast() & lmask]; dolen: bi_.drop(cp->bits); op = (unsigned)(cp->op); if(op == 0) { // literal *r.out.next++ = (unsigned char)(cp->val); } else if(op & 16) { // length base len = (unsigned)(cp->val); op &= 15; // number of extra bits if(op) { if(bi_.size() < op) bi_.fill_8(r.in.next); len += (unsigned)bi_.peek_fast() & ((1U << op) - 1); bi_.drop(op); } if(bi_.size() < 15) bi_.fill_16(r.in.next); cp = &distcode_[bi_.peek_fast() & dmask]; dodist: bi_.drop(cp->bits); op = (unsigned)(cp->op); if(op & 16) { // distance base dist = (unsigned)(cp->val); op &= 15; // number of extra bits if(bi_.size() < op) { bi_.fill_8(r.in.next); if(bi_.size() < op) bi_.fill_8(r.in.next); } dist += (unsigned)bi_.peek_fast() & ((1U << op) - 1); #ifdef INFLATE_STRICT if(dist > dmax_) { ec = error::invalid_distance; mode_ = BAD; break; } #endif bi_.drop(op); op = r.out.used(); if(dist > op) { // copy from window op = dist - op; // distance back in window if(op > w_.size()) { ec = error::invalid_distance; mode_ = BAD; break; } auto const n = clamp(len, op); w_.read(r.out.next, op, n); r.out.next += n; len -= n; } if(len > 0) { // copy from output auto in = r.out.next - dist; auto n = clamp(len, r.out.avail()); len -= n; while(n--) *r.out.next++ = *in++; } } else if((op & 64) == 0) { // 2nd level distance code cp = &distcode_[cp->val + (bi_.peek_fast() & ((1U << op) - 1))]; goto dodist; } else { ec = error::invalid_distance_code; mode_ = BAD; break; } } else if((op & 64) == 0) { // 2nd level length code cp = &lencode_[cp->val + (bi_.peek_fast() & ((1U << op) - 1))]; goto dolen; } else if(op & 32) { // end-of-block mode_ = TYPE; break; } else { ec = error::invalid_literal_length; mode_ = BAD; break; } } while(r.in.next < last && r.out.next < end); // return unused bytes (on entry, bits < 8, so in won't go too far back) bi_.rewind(r.in.next); } } // detail } // zlib } // beast } // boost #endif PK OP�[��Lj � zlib/detail/window.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_DETAIL_WINDOW_HPP #define BOOST_BEAST_ZLIB_DETAIL_WINDOW_HPP #include <boost/assert.hpp> #include <boost/make_unique.hpp> #include <cstdint> #include <cstring> #include <memory> namespace boost { namespace beast { namespace zlib { namespace detail { class window { std::unique_ptr<std::uint8_t[]> p_; std::uint16_t i_ = 0; std::uint16_t size_ = 0; std::uint16_t capacity_ = 0; std::uint8_t bits_ = 0; public: int bits() const { return bits_; } unsigned capacity() const { return capacity_; } unsigned size() const { return size_; } void reset(int bits) { if(bits_ != bits) { p_.reset(); bits_ = static_cast<std::uint8_t>(bits); capacity_ = 1U << bits_; } i_ = 0; size_ = 0; } void read(std::uint8_t* out, std::size_t pos, std::size_t n) { if(i_ >= size_) { // window is contiguous std::memcpy(out, &p_[i_ - pos], n); return; } auto i = ((i_ - pos) + capacity_) % capacity_; auto m = capacity_ - i; if(n <= m) { std::memcpy(out, &p_[i], n); return; } std::memcpy(out, &p_[i], m); out += m; std::memcpy(out, &p_[0], n - m); } void write(std::uint8_t const* in, std::size_t n) { if(! p_) p_ = boost::make_unique< std::uint8_t[]>(capacity_); if(n >= capacity_) { i_ = 0; size_ = capacity_; std::memcpy(&p_[0], in + (n - size_), size_); return; } if(i_ + n <= capacity_) { std::memcpy(&p_[i_], in, n); if(size_ >= capacity_ - n) size_ = capacity_; else size_ = static_cast<std::uint16_t>(size_ + n); i_ = static_cast<std::uint16_t>( (i_ + n) % capacity_); return; } auto m = capacity_ - i_; std::memcpy(&p_[i_], in, m); in += m; i_ = static_cast<std::uint16_t>(n - m); std::memcpy(&p_[0], in, i_); size_ = capacity_; } }; } // detail } // zlib } // beast } // boost #endif PK OP�[��?. . zlib/detail/deflate_stream.ippnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_DETAIL_DEFLATE_STREAM_IPP #define BOOST_BEAST_ZLIB_DETAIL_DEFLATE_STREAM_IPP #include <boost/beast/zlib/detail/deflate_stream.hpp> #include <boost/beast/zlib/detail/ranges.hpp> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/make_unique.hpp> #include <boost/optional.hpp> #include <boost/throw_exception.hpp> #include <cstdint> #include <cstdlib> #include <cstring> #include <memory> #include <stdexcept> #include <type_traits> namespace boost { namespace beast { namespace zlib { namespace detail { /* * ALGORITHM * * The "deflation" process depends on being able to identify portions * of the input text which are identical to earlier input (within a * sliding window trailing behind the input currently being processed). * * Each code tree is stored in a compressed form which is itself * a Huffman encoding of the lengths of all the code strings (in * ascending order by source values). The actual code strings are * reconstructed from the lengths in the inflate process, as described * in the deflate specification. * * The most straightforward technique turns out to be the fastest for * most input files: try all possible matches and select the longest. * The key feature of this algorithm is that insertions into the string * dictionary are very simple and thus fast, and deletions are avoided * completely. Insertions are performed at each input character, whereas * string matches are performed only when the previous match ends. So it * is preferable to spend more time in matches to allow very fast string * insertions and avoid deletions. The matching algorithm for small * strings is inspired from that of Rabin & Karp. A brute force approach * is used to find longer strings when a small match has been found. * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze * (by Leonid Broukhis). * A previous version of this file used a more sophisticated algorithm * (by Fiala and Greene) which is guaranteed to run in linear amortized * time, but has a larger average cost, uses more memory and is patented. * However the F&G algorithm may be faster for some highly redundant * files if the parameter max_chain_length (described below) is too large. * * ACKNOWLEDGEMENTS * * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and * I found it in 'freeze' written by Leonid Broukhis. * Thanks to many people for bug reports and testing. * * REFERENCES * * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". * Available in http://tools.ietf.org/html/rfc1951 * * A description of the Rabin and Karp algorithm is given in the book * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. * * Fiala,E.R., and Greene,D.H. * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 * */ /* Generate the codes for a given tree and bit counts (which need not be optimal). IN assertion: the array bl_count contains the bit length statistics for the given tree and the field len is set for all tree elements. OUT assertion: the field code is set for all tree elements of non zero code length. */ void deflate_stream:: gen_codes(ct_data *tree, int max_code, std::uint16_t *bl_count) { std::uint16_t next_code[maxBits+1]; /* next code value for each bit length */ std::uint16_t code = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ // The distribution counts are first used to // generate the code values without bit reversal. for(bits = 1; bits <= maxBits; bits++) { code = (code + bl_count[bits-1]) << 1; next_code[bits] = code; } // Check that the bit counts in bl_count are consistent. // The last code must be all ones. BOOST_ASSERT(code + bl_count[maxBits]-1 == (1<<maxBits)-1); for(n = 0; n <= max_code; n++) { int len = tree[n].dl; if(len == 0) continue; tree[n].fc = bi_reverse(next_code[len]++, len); } } auto deflate_stream::get_lut() -> lut_type const& { struct init { lut_type tables; init() { // number of codes at each bit length for an optimal tree //std::uint16_t bl_count[maxBits+1]; // Initialize the mapping length (0..255) -> length code (0..28) std::uint8_t length = 0; for(std::uint8_t code = 0; code < lengthCodes-1; ++code) { tables.base_length[code] = length; auto const run = 1U << tables.extra_lbits[code]; for(unsigned n = 0; n < run; ++n) tables.length_code[length++] = code; } BOOST_ASSERT(length == 0); // Note that the length 255 (match length 258) can be represented // in two different ways: code 284 + 5 bits or code 285, so we // overwrite length_code[255] to use the best encoding: tables.length_code[255] = lengthCodes-1; // Initialize the mapping dist (0..32K) -> dist code (0..29) { std::uint8_t code; std::uint16_t dist = 0; for(code = 0; code < 16; code++) { tables.base_dist[code] = dist; auto const run = 1U << tables.extra_dbits[code]; for(unsigned n = 0; n < run; ++n) tables.dist_code[dist++] = code; } BOOST_ASSERT(dist == 256); // from now on, all distances are divided by 128 dist >>= 7; for(; code < dCodes; ++code) { tables.base_dist[code] = dist << 7; auto const run = 1U << (tables.extra_dbits[code]-7); for(std::size_t n = 0; n < run; ++n) tables.dist_code[256 + dist++] = code; } BOOST_ASSERT(dist == 256); } // Construct the codes of the static literal tree std::uint16_t bl_count[maxBits+1]; std::memset(bl_count, 0, sizeof(bl_count)); unsigned n = 0; while (n <= 143) tables.ltree[n++].dl = 8; bl_count[8] += 144; while (n <= 255) tables.ltree[n++].dl = 9; bl_count[9] += 112; while (n <= 279) tables.ltree[n++].dl = 7; bl_count[7] += 24; while (n <= 287) tables.ltree[n++].dl = 8; bl_count[8] += 8; // Codes 286 and 287 do not exist, but we must include them in the tree // construction to get a canonical Huffman tree (longest code all ones) gen_codes(tables.ltree, lCodes+1, bl_count); for(n = 0; n < dCodes; ++n) { tables.dtree[n].dl = 5; tables.dtree[n].fc = static_cast<std::uint16_t>(bi_reverse(n, 5)); } } }; static init const data; return data.tables; } void deflate_stream:: doReset( int level, int windowBits, int memLevel, Strategy strategy) { if(level == default_size) level = 6; // VFALCO What do we do about this? // until 256-byte window bug fixed if(windowBits == 8) windowBits = 9; if(level < 0 || level > 9) BOOST_THROW_EXCEPTION(std::invalid_argument{ "invalid level"}); if(windowBits < 8 || windowBits > 15) BOOST_THROW_EXCEPTION(std::invalid_argument{ "invalid windowBits"}); if(memLevel < 1 || memLevel > max_mem_level) BOOST_THROW_EXCEPTION(std::invalid_argument{ "invalid memLevel"}); w_bits_ = windowBits; hash_bits_ = memLevel + 7; // 16K elements by default lit_bufsize_ = 1 << (memLevel + 6); level_ = level; strategy_ = strategy; inited_ = false; } void deflate_stream:: doReset() { inited_ = false; } void deflate_stream:: doClear() { inited_ = false; buf_.reset(); } std::size_t deflate_stream:: doUpperBound(std::size_t sourceLen) const { std::size_t complen; std::size_t wraplen; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* compute wrapper length */ wraplen = 0; /* if not default parameters, return conservative bound */ if(w_bits_ != 15 || hash_bits_ != 8 + 7) return complen + wraplen; /* default settings: return tight bound for that case */ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen; } void deflate_stream:: doTune( int good_length, int max_lazy, int nice_length, int max_chain) { good_match_ = good_length; nice_match_ = nice_length; max_lazy_match_ = max_lazy; max_chain_length_ = max_chain; } void deflate_stream:: doParams(z_params& zs, int level, Strategy strategy, error_code& ec) { compress_func func; if(level == default_size) level = 6; if(level < 0 || level > 9) { ec = error::stream_error; return; } func = get_config(level_).func; if((strategy != strategy_ || func != get_config(level).func) && zs.total_in != 0) { // Flush the last buffer: doWrite(zs, Flush::block, ec); if(ec == error::need_buffers && pending_ == 0) ec = {}; } if(level_ != level) { level_ = level; max_lazy_match_ = get_config(level).max_lazy; good_match_ = get_config(level).good_length; nice_match_ = get_config(level).nice_length; max_chain_length_ = get_config(level).max_chain; } strategy_ = strategy; } // VFALCO boost::optional param is a workaround for // gcc "maybe uninitialized" warning // https://github.com/boostorg/beast/issues/532 // void deflate_stream:: doWrite(z_params& zs, boost::optional<Flush> flush, error_code& ec) { maybe_init(); if(zs.next_in == nullptr && zs.avail_in != 0) BOOST_THROW_EXCEPTION(std::invalid_argument{"invalid input"}); if(zs.next_out == nullptr || (status_ == FINISH_STATE && flush != Flush::finish)) { ec = error::stream_error; return; } if(zs.avail_out == 0) { ec = error::need_buffers; return; } // value of flush param for previous deflate call auto old_flush = boost::make_optional<Flush>( last_flush_.is_initialized(), last_flush_ ? *last_flush_ : Flush::none); last_flush_ = flush; // Flush as much pending output as possible if(pending_ != 0) { flush_pending(zs); if(zs.avail_out == 0) { /* Since avail_out is 0, deflate will be called again with * more output space, but possibly with both pending and * avail_in equal to zero. There won't be anything to do, * but this is not an error situation so make sure we * return OK instead of BUF_ERROR at next call of deflate: */ last_flush_ = boost::none; return; } } else if(zs.avail_in == 0 && ( old_flush && flush <= *old_flush // Caution: depends on enum order ) && flush != Flush::finish) { /* Make sure there is something to do and avoid duplicate consecutive * flushes. For repeated and useless calls with Flush::finish, we keep * returning Z_STREAM_END instead of Z_BUF_ERROR. */ ec = error::need_buffers; return; } // User must not provide more input after the first FINISH: if(status_ == FINISH_STATE && zs.avail_in != 0) { ec = error::need_buffers; return; } /* Start a new block or continue the current one. */ if(zs.avail_in != 0 || lookahead_ != 0 || (flush != Flush::none && status_ != FINISH_STATE)) { block_state bstate; switch(strategy_) { case Strategy::huffman: bstate = deflate_huff(zs, flush.get()); break; case Strategy::rle: bstate = deflate_rle(zs, flush.get()); break; default: { bstate = (this->*(get_config(level_).func))(zs, flush.get()); break; } } if(bstate == finish_started || bstate == finish_done) { status_ = FINISH_STATE; } if(bstate == need_more || bstate == finish_started) { if(zs.avail_out == 0) { last_flush_ = boost::none; /* avoid BUF_ERROR next call, see above */ } return; /* If flush != Flush::none && avail_out == 0, the next call of deflate should use the same flush parameter to make sure that the flush is complete. So we don't have to output an empty block here, this will be done at next call. This also ensures that for a very small output buffer, we emit at most one empty block. */ } if(bstate == block_done) { if(flush == Flush::partial) { tr_align(); } else if(flush != Flush::block) { /* FULL_FLUSH or SYNC_FLUSH */ tr_stored_block(nullptr, 0L, 0); /* For a full flush, this empty block will be recognized * as a special marker by inflate_sync(). */ if(flush == Flush::full) { clear_hash(); // forget history if(lookahead_ == 0) { strstart_ = 0; block_start_ = 0L; insert_ = 0; } } } flush_pending(zs); if(zs.avail_out == 0) { last_flush_ = boost::none; /* avoid BUF_ERROR at next call, see above */ return; } } } if(flush == Flush::finish) { ec = error::end_of_stream; return; } } // VFALCO Warning: untested void deflate_stream:: doDictionary(Byte const* dict, uInt dictLength, error_code& ec) { if(lookahead_) { ec = error::stream_error; return; } maybe_init(); /* if dict would fill window, just replace the history */ if(dictLength >= w_size_) { clear_hash(); strstart_ = 0; block_start_ = 0L; insert_ = 0; dict += dictLength - w_size_; /* use the tail */ dictLength = w_size_; } /* insert dict into window and hash */ z_params zs; zs.avail_in = dictLength; zs.next_in = (const Byte *)dict; zs.avail_out = 0; zs.next_out = 0; fill_window(zs); while(lookahead_ >= minMatch) { uInt str = strstart_; uInt n = lookahead_ - (minMatch-1); do { update_hash(ins_h_, window_[str + minMatch-1]); prev_[str & w_mask_] = head_[ins_h_]; head_[ins_h_] = (std::uint16_t)str; str++; } while(--n); strstart_ = str; lookahead_ = minMatch-1; fill_window(zs); } strstart_ += lookahead_; block_start_ = (long)strstart_; insert_ = lookahead_; lookahead_ = 0; match_length_ = prev_length_ = minMatch-1; match_available_ = 0; } void deflate_stream:: doPrime(int bits, int value, error_code& ec) { maybe_init(); if((Byte *)(d_buf_) < pending_out_ + ((Buf_size + 7) >> 3)) { ec = error::need_buffers; return; } do { int put = Buf_size - bi_valid_; if(put > bits) put = bits; bi_buf_ |= (std::uint16_t)((value & ((1 << put) - 1)) << bi_valid_); bi_valid_ += put; tr_flush_bits(); value >>= put; bits -= put; } while(bits); } void deflate_stream:: doPending(unsigned* value, int* bits) { if(value != 0) *value = pending_; if(bits != 0) *bits = bi_valid_; } //-------------------------------------------------------------------------- // Do lazy initialization void deflate_stream:: init() { // Caller must set these: // w_bits_ // hash_bits_ // lit_bufsize_ // level_ // strategy_ w_size_ = 1 << w_bits_; w_mask_ = w_size_ - 1; hash_size_ = 1 << hash_bits_; hash_mask_ = hash_size_ - 1; hash_shift_ = ((hash_bits_+minMatch-1)/minMatch); auto const nwindow = w_size_ * 2*sizeof(Byte); auto const nprev = w_size_ * sizeof(std::uint16_t); auto const nhead = hash_size_ * sizeof(std::uint16_t); auto const noverlay = lit_bufsize_ * (sizeof(std::uint16_t)+2); auto const needed = nwindow + nprev + nhead + noverlay; if(! buf_ || buf_size_ != needed) { buf_ = boost::make_unique_noinit< std::uint8_t[]>(needed); buf_size_ = needed; } window_ = reinterpret_cast<Byte*>(buf_.get()); prev_ = reinterpret_cast<std::uint16_t*>(buf_.get() + nwindow); std::memset(prev_, 0, nprev); head_ = reinterpret_cast<std::uint16_t*>(buf_.get() + nwindow + nprev); /* We overlay pending_buf_ and d_buf_ + l_buf_. This works since the average output size for(length, distance) codes is <= 24 bits. */ auto overlay = reinterpret_cast<std::uint16_t*>( buf_.get() + nwindow + nprev + nhead); // nothing written to window_ yet high_water_ = 0; pending_buf_ = reinterpret_cast<std::uint8_t*>(overlay); pending_buf_size_ = static_cast<std::uint32_t>(lit_bufsize_) * (sizeof(std::uint16_t) + 2L); d_buf_ = overlay + lit_bufsize_ / sizeof(std::uint16_t); l_buf_ = pending_buf_ + (1 + sizeof(std::uint16_t)) * lit_bufsize_; pending_ = 0; pending_out_ = pending_buf_; status_ = BUSY_STATE; last_flush_ = Flush::none; tr_init(); lm_init(); inited_ = true; } /* Initialize the "longest match" routines for a new zlib stream */ void deflate_stream:: lm_init() { window_size_ = (std::uint32_t)2L*w_size_; clear_hash(); /* Set the default configuration parameters: */ // VFALCO TODO just copy the config struct max_lazy_match_ = get_config(level_).max_lazy; good_match_ = get_config(level_).good_length; nice_match_ = get_config(level_).nice_length; max_chain_length_ = get_config(level_).max_chain; strstart_ = 0; block_start_ = 0L; lookahead_ = 0; insert_ = 0; match_length_ = prev_length_ = minMatch-1; match_available_ = 0; ins_h_ = 0; } // Initialize a new block. // void deflate_stream:: init_block() { for(int n = 0; n < lCodes; n++) dyn_ltree_[n].fc = 0; for(int n = 0; n < dCodes; n++) dyn_dtree_[n].fc = 0; for(int n = 0; n < blCodes; n++) bl_tree_[n].fc = 0; dyn_ltree_[END_BLOCK].fc = 1; opt_len_ = 0L; static_len_ = 0L; last_lit_ = 0; matches_ = 0; } /* Restore the heap property by moving down the tree starting at node k, exchanging a node with the smallest of its two sons if necessary, stopping when the heap property is re-established (each father smaller than its two sons). */ void deflate_stream:: pqdownheap( ct_data const* tree, // the tree to restore int k) // node to move down { int v = heap_[k]; int j = k << 1; // left son of k while(j <= heap_len_) { // Set j to the smallest of the two sons: if(j < heap_len_ && smaller(tree, heap_[j+1], heap_[j])) j++; // Exit if v is smaller than both sons if(smaller(tree, v, heap_[j])) break; // Exchange v with the smallest son heap_[k] = heap_[j]; k = j; // And continue down the tree, // setting j to the left son of k j <<= 1; } heap_[k] = v; } /* Remove the smallest element from the heap and recreate the heap with one less element. Updates heap and heap_len. */ void deflate_stream:: pqremove(ct_data const* tree, int& top) { top = heap_[kSmallest]; heap_[kSmallest] = heap_[heap_len_--]; pqdownheap(tree, kSmallest); } /* Compute the optimal bit lengths for a tree and update the total bit length for the current block. IN assertion: the fields freq and dad are set, heap[heap_max] and above are the tree nodes sorted by increasing frequency. OUT assertions: the field len is set to the optimal bit length, the array bl_count contains the frequencies for each bit length. The length opt_len is updated; static_len is also updated if stree is not null. */ void deflate_stream:: gen_bitlen(tree_desc *desc) { ct_data *tree = desc->dyn_tree; int max_code = desc->max_code; ct_data const* stree = desc->stat_desc->static_tree; std::uint8_t const *extra = desc->stat_desc->extra_bits; int base = desc->stat_desc->extra_base; int max_length = desc->stat_desc->max_length; int h; // heap index int n, m; // iterate over the tree elements int bits; // bit length int xbits; // extra bits std::uint16_t f; // frequency int overflow = 0; // number of elements with bit length too large std::fill(&bl_count_[0], &bl_count_[maxBits+1], std::uint16_t{0}); /* In a first pass, compute the optimal bit lengths (which may * overflow in the case of the bit length tree). */ tree[heap_[heap_max_]].dl = 0; // root of the heap for(h = heap_max_+1; h < HEAP_SIZE; h++) { n = heap_[h]; bits = tree[tree[n].dl].dl + 1; if(bits > max_length) bits = max_length, overflow++; // We overwrite tree[n].dl which is no longer needed tree[n].dl = (std::uint16_t)bits; if(n > max_code) continue; // not a leaf node bl_count_[bits]++; xbits = 0; if(n >= base) xbits = extra[n-base]; f = tree[n].fc; opt_len_ += (std::uint32_t)f * (bits + xbits); if(stree) static_len_ += (std::uint32_t)f * (stree[n].dl + xbits); } if(overflow == 0) return; // Find the first bit length which could increase: do { bits = max_length-1; while(bl_count_[bits] == 0) bits--; bl_count_[bits]--; // move one leaf down the tree bl_count_[bits+1] += 2; // move one overflow item as its brother bl_count_[max_length]--; /* The brother of the overflow item also moves one step up, * but this does not affect bl_count[max_length] */ overflow -= 2; } while(overflow > 0); /* Now recompute all bit lengths, scanning in increasing frequency. * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all * lengths instead of fixing only the wrong ones. This idea is taken * from 'ar' written by Haruhiko Okumura.) */ for(bits = max_length; bits != 0; bits--) { n = bl_count_[bits]; while(n != 0) { m = heap_[--h]; if(m > max_code) continue; if((unsigned) tree[m].dl != (unsigned) bits) { opt_len_ += ((long)bits - (long)tree[m].dl) *(long)tree[m].fc; tree[m].dl = (std::uint16_t)bits; } n--; } } } /* Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block. IN assertion: the field freq is set for all tree elements. OUT assertions: the fields len and code are set to the optimal bit length and corresponding code. The length opt_len is updated; static_len is also updated if stree is not null. The field max_code is set. */ void deflate_stream:: build_tree(tree_desc *desc) { ct_data *tree = desc->dyn_tree; ct_data const* stree = desc->stat_desc->static_tree; int elems = desc->stat_desc->elems; int n, m; // iterate over heap elements int max_code = -1; // largest code with non zero frequency int node; // new node being created /* Construct the initial heap, with least frequent element in * heap[kSmallest]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[0] is not used. */ heap_len_ = 0; heap_max_ = HEAP_SIZE; for(n = 0; n < elems; n++) { if(tree[n].fc != 0) { heap_[++(heap_len_)] = max_code = n; depth_[n] = 0; } else { tree[n].dl = 0; } } /* The pkzip format requires that at least one distance code exists, * and that at least one bit should be sent even if there is only one * possible code. So to avoid special checks later on we force at least * two codes of non zero frequency. */ while(heap_len_ < 2) { node = heap_[++(heap_len_)] = (max_code < 2 ? ++max_code : 0); tree[node].fc = 1; depth_[node] = 0; opt_len_--; if(stree) static_len_ -= stree[node].dl; // node is 0 or 1 so it does not have extra bits } desc->max_code = max_code; /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, * establish sub-heaps of increasing lengths: */ for(n = heap_len_/2; n >= 1; n--) pqdownheap(tree, n); /* Construct the Huffman tree by repeatedly combining the least two * frequent nodes. */ node = elems; /* next internal node of the tree */ do { pqremove(tree, n); /* n = node of least frequency */ m = heap_[kSmallest]; /* m = node of next least frequency */ heap_[--(heap_max_)] = n; /* keep the nodes sorted by frequency */ heap_[--(heap_max_)] = m; /* Create a new node father of n and m */ tree[node].fc = tree[n].fc + tree[m].fc; depth_[node] = (std::uint8_t)((depth_[n] >= depth_[m] ? depth_[n] : depth_[m]) + 1); tree[n].dl = tree[m].dl = (std::uint16_t)node; /* and insert the new node in the heap */ heap_[kSmallest] = node++; pqdownheap(tree, kSmallest); } while(heap_len_ >= 2); heap_[--(heap_max_)] = heap_[kSmallest]; /* At this point, the fields freq and dad are set. We can now * generate the bit lengths. */ gen_bitlen((tree_desc *)desc); /* The field len is now set, we can generate the bit codes */ gen_codes(tree, max_code, bl_count_); } /* Scan a literal or distance tree to determine the frequencies of the codes in the bit length tree. */ void deflate_stream:: scan_tree( ct_data *tree, // the tree to be scanned int max_code) // and its largest code of non zero frequency { int n; // iterates over all tree elements int prevlen = -1; // last emitted length int curlen; // length of current code int nextlen = tree[0].dl; // length of next code std::uint16_t count = 0; // repeat count of the current code int max_count = 7; // max repeat count int min_count = 4; // min repeat count if(nextlen == 0) { max_count = 138; min_count = 3; } tree[max_code+1].dl = (std::uint16_t)0xffff; // guard for(n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].dl; if(++count < max_count && curlen == nextlen) { continue; } else if(count < min_count) { bl_tree_[curlen].fc += count; } else if(curlen != 0) { if(curlen != prevlen) bl_tree_[curlen].fc++; bl_tree_[REP_3_6].fc++; } else if(count <= 10) { bl_tree_[REPZ_3_10].fc++; } else { bl_tree_[REPZ_11_138].fc++; } count = 0; prevlen = curlen; if(nextlen == 0) { max_count = 138; min_count = 3; } else if(curlen == nextlen) { max_count = 6; min_count = 3; } else { max_count = 7; min_count = 4; } } } /* Send a literal or distance tree in compressed form, using the codes in bl_tree. */ void deflate_stream:: send_tree( ct_data *tree, // the tree to be scanned int max_code) // and its largest code of non zero frequency { int n; // iterates over all tree elements int prevlen = -1; // last emitted length int curlen; // length of current code int nextlen = tree[0].dl; // length of next code int count = 0; // repeat count of the current code int max_count = 7; // max repeat count int min_count = 4; // min repeat count // tree[max_code+1].dl = -1; // guard already set if(nextlen == 0) { max_count = 138; min_count = 3; } for(n = 0; n <= max_code; n++) { curlen = nextlen; nextlen = tree[n+1].dl; if(++count < max_count && curlen == nextlen) { continue; } else if(count < min_count) { do { send_code(curlen, bl_tree_); } while (--count != 0); } else if(curlen != 0) { if(curlen != prevlen) { send_code(curlen, bl_tree_); count--; } BOOST_ASSERT(count >= 3 && count <= 6); send_code(REP_3_6, bl_tree_); send_bits(count-3, 2); } else if(count <= 10) { send_code(REPZ_3_10, bl_tree_); send_bits(count-3, 3); } else { send_code(REPZ_11_138, bl_tree_); send_bits(count-11, 7); } count = 0; prevlen = curlen; if(nextlen == 0) { max_count = 138; min_count = 3; } else if(curlen == nextlen) { max_count = 6; min_count = 3; } else { max_count = 7; min_count = 4; } } } /* Construct the Huffman tree for the bit lengths and return the index in bl_order of the last bit length code to send. */ int deflate_stream:: build_bl_tree() { int max_blindex; // index of last bit length code of non zero freq // Determine the bit length frequencies for literal and distance trees scan_tree((ct_data *)dyn_ltree_, l_desc_.max_code); scan_tree((ct_data *)dyn_dtree_, d_desc_.max_code); // Build the bit length tree: build_tree((tree_desc *)(&(bl_desc_))); /* opt_len now includes the length of the tree representations, except * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. */ /* Determine the number of bit length codes to send. The pkzip format * requires that at least 4 bit length codes be sent. (appnote.txt says * 3 but the actual value used is 4.) */ for(max_blindex = blCodes-1; max_blindex >= 3; max_blindex--) { if(bl_tree_[lut_.bl_order[max_blindex]].dl != 0) break; } // Update opt_len to include the bit length tree and counts opt_len_ += 3*(max_blindex+1) + 5+5+4; return max_blindex; } /* Send the header for a block using dynamic Huffman trees: the counts, the lengths of the bit length codes, the literal tree and the distance tree. IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. */ void deflate_stream:: send_all_trees( int lcodes, int dcodes, int blcodes) // number of codes for each tree { int rank; // index in bl_order BOOST_ASSERT(lcodes >= 257 && dcodes >= 1 && blcodes >= 4); BOOST_ASSERT(lcodes <= lCodes && dcodes <= dCodes && blcodes <= blCodes); send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt send_bits(dcodes-1, 5); send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt for(rank = 0; rank < blcodes; rank++) send_bits(bl_tree_[lut_.bl_order[rank]].dl, 3); send_tree((ct_data *)dyn_ltree_, lcodes-1); // literal tree send_tree((ct_data *)dyn_dtree_, dcodes-1); // distance tree } /* Send the block data compressed using the given Huffman trees */ void deflate_stream:: compress_block( ct_data const* ltree, // literal tree ct_data const* dtree) // distance tree { unsigned dist; /* distance of matched string */ int lc; /* match length or unmatched char (if dist == 0) */ unsigned lx = 0; /* running index in l_buf */ unsigned code; /* the code to send */ int extra; /* number of extra bits to send */ if(last_lit_ != 0) { do { dist = d_buf_[lx]; lc = l_buf_[lx++]; if(dist == 0) { send_code(lc, ltree); /* send a literal byte */ } else { /* Here, lc is the match length - minMatch */ code = lut_.length_code[lc]; send_code(code+literals+1, ltree); /* send the length code */ extra = lut_.extra_lbits[code]; if(extra != 0) { lc -= lut_.base_length[code]; send_bits(lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ code = d_code(dist); BOOST_ASSERT(code < dCodes); send_code(code, dtree); /* send the distance code */ extra = lut_.extra_dbits[code]; if(extra != 0) { dist -= lut_.base_dist[code]; send_bits(dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ BOOST_ASSERT((uInt)(pending_) < lit_bufsize_ + 2*lx); } while(lx < last_lit_); } send_code(END_BLOCK, ltree); } /* Check if the data type is TEXT or BINARY, using the following algorithm: - TEXT if the two conditions below are satisfied: a) There are no non-portable control characters belonging to the "black list" (0..6, 14..25, 28..31). b) There is at least one printable character belonging to the "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255). - BINARY otherwise. - The following partially-portable control characters form a "gray list" that is ignored in this detection algorithm: (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}). IN assertion: the fields fc of dyn_ltree are set. */ int deflate_stream:: detect_data_type() { /* black_mask is the bit mask of black-listed bytes * set bits 0..6, 14..25, and 28..31 * 0xf3ffc07f = binary 11110011111111111100000001111111 */ unsigned long black_mask = 0xf3ffc07fUL; int n; // Check for non-textual ("black-listed") bytes. for(n = 0; n <= 31; n++, black_mask >>= 1) if((black_mask & 1) && (dyn_ltree_[n].fc != 0)) return binary; // Check for textual ("white-listed") bytes. */ if(dyn_ltree_[9].fc != 0 || dyn_ltree_[10].fc != 0 || dyn_ltree_[13].fc != 0) return text; for(n = 32; n < literals; n++) if(dyn_ltree_[n].fc != 0) return text; /* There are no "black-listed" or "white-listed" bytes: * this stream either is empty or has tolerated ("gray-listed") bytes only. */ return binary; } /* Flush the bit buffer and align the output on a byte boundary */ void deflate_stream:: bi_windup() { if(bi_valid_ > 8) put_short(bi_buf_); else if(bi_valid_ > 0) put_byte((Byte)bi_buf_); bi_buf_ = 0; bi_valid_ = 0; } /* Flush the bit buffer, keeping at most 7 bits in it. */ void deflate_stream:: bi_flush() { if(bi_valid_ == 16) { put_short(bi_buf_); bi_buf_ = 0; bi_valid_ = 0; } else if(bi_valid_ >= 8) { put_byte((Byte)bi_buf_); bi_buf_ >>= 8; bi_valid_ -= 8; } } /* Copy a stored block, storing first the length and its one's complement if requested. */ void deflate_stream:: copy_block( char *buf, // the input data unsigned len, // its length int header) // true if block header must be written { bi_windup(); // align on byte boundary if(header) { put_short((std::uint16_t)len); put_short((std::uint16_t)~len); } if(buf) std::memcpy(&pending_buf_[pending_], buf, len); pending_ += len; } //------------------------------------------------------------------------------ /* Initialize the tree data structures for a new zlib stream. */ void deflate_stream:: tr_init() { l_desc_.dyn_tree = dyn_ltree_; l_desc_.stat_desc = &lut_.l_desc; d_desc_.dyn_tree = dyn_dtree_; d_desc_.stat_desc = &lut_.d_desc; bl_desc_.dyn_tree = bl_tree_; bl_desc_.stat_desc = &lut_.bl_desc; bi_buf_ = 0; bi_valid_ = 0; // Initialize the first block of the first file: init_block(); } /* Send one empty static block to give enough lookahead for inflate. This takes 10 bits, of which 7 may remain in the bit buffer. */ void deflate_stream:: tr_align() { send_bits(STATIC_TREES<<1, 3); send_code(END_BLOCK, lut_.ltree); bi_flush(); } /* Flush the bits in the bit buffer to pending output (leaves at most 7 bits) */ void deflate_stream:: tr_flush_bits() { bi_flush(); } /* Send a stored block */ void deflate_stream:: tr_stored_block( char *buf, // input block std::uint32_t stored_len, // length of input block int last) // one if this is the last block for a file { send_bits((STORED_BLOCK<<1)+last, 3); // send block type copy_block(buf, (unsigned)stored_len, 1); // with header } void deflate_stream:: tr_tally_dist(std::uint16_t dist, std::uint8_t len, bool& flush) { d_buf_[last_lit_] = dist; l_buf_[last_lit_++] = len; dist--; dyn_ltree_[lut_.length_code[len]+literals+1].fc++; dyn_dtree_[d_code(dist)].fc++; flush = (last_lit_ == lit_bufsize_-1); } void deflate_stream:: tr_tally_lit(std::uint8_t c, bool& flush) { d_buf_[last_lit_] = 0; l_buf_[last_lit_++] = c; dyn_ltree_[c].fc++; flush = (last_lit_ == lit_bufsize_-1); } //------------------------------------------------------------------------------ /* Determine the best encoding for the current block: dynamic trees, static trees or store, and output the encoded block to the zip file. */ void deflate_stream:: tr_flush_block( z_params& zs, char *buf, // input block, or NULL if too old std::uint32_t stored_len, // length of input block int last) // one if this is the last block for a file { std::uint32_t opt_lenb; std::uint32_t static_lenb; // opt_len and static_len in bytes int max_blindex = 0; // index of last bit length code of non zero freq // Build the Huffman trees unless a stored block is forced if(level_ > 0) { // Check if the file is binary or text if(zs.data_type == unknown) zs.data_type = detect_data_type(); // Construct the literal and distance trees build_tree((tree_desc *)(&(l_desc_))); build_tree((tree_desc *)(&(d_desc_))); /* At this point, opt_len and static_len are the total bit lengths of * the compressed block data, excluding the tree representations. */ /* Build the bit length tree for the above two trees, and get the index * in bl_order of the last bit length code to send. */ max_blindex = build_bl_tree(); /* Determine the best encoding. Compute the block lengths in bytes. */ opt_lenb = (opt_len_+3+7)>>3; static_lenb = (static_len_+3+7)>>3; if(static_lenb <= opt_lenb) opt_lenb = static_lenb; } else { // VFALCO This assertion fails even in the original ZLib, // happens with strategy == Z_HUFFMAN_ONLY, see: // https://github.com/madler/zlib/issues/172 #if 0 BOOST_ASSERT(buf); #endif opt_lenb = static_lenb = stored_len + 5; // force a stored block } #ifdef FORCE_STORED if(buf != (char*)0) { /* force stored block */ #else if(stored_len+4 <= opt_lenb && buf != (char*)0) { /* 4: two words for the lengths */ #endif /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. * Otherwise we can't have processed more than WSIZE input bytes since * the last block flush, because compression would have been * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * transform a block into a stored block. */ tr_stored_block(buf, stored_len, last); #ifdef FORCE_STATIC } else if(static_lenb >= 0) { // force static trees #else } else if(strategy_ == Strategy::fixed || static_lenb == opt_lenb) { #endif send_bits((STATIC_TREES<<1)+last, 3); compress_block(lut_.ltree, lut_.dtree); } else { send_bits((DYN_TREES<<1)+last, 3); send_all_trees(l_desc_.max_code+1, d_desc_.max_code+1, max_blindex+1); compress_block((const ct_data *)dyn_ltree_, (const ct_data *)dyn_dtree_); } /* The above check is made mod 2^32, for files larger than 512 MB * and std::size_t implemented on 32 bits. */ init_block(); if(last) bi_windup(); } void deflate_stream:: fill_window(z_params& zs) { unsigned n, m; unsigned more; // Amount of free space at the end of the window. std::uint16_t *p; uInt wsize = w_size_; do { more = (unsigned)(window_size_ - (std::uint32_t)lookahead_ -(std::uint32_t)strstart_); // VFALCO We don't support systems below 32-bit #if 0 // Deal with !@#$% 64K limit: if(sizeof(int) <= 2) { if(more == 0 && strstart_ == 0 && lookahead_ == 0) { more = wsize; } else if(more == (unsigned)(-1)) { /* Very unlikely, but possible on 16 bit machine if * strstart == 0 && lookahead == 1 (input done a byte at time) */ more--; } } #endif /* If the window is almost full and there is insufficient lookahead, move the upper half to the lower one to make room in the upper half. */ if(strstart_ >= wsize+max_dist()) { std::memcpy(window_, window_+wsize, (unsigned)wsize); match_start_ -= wsize; strstart_ -= wsize; // we now have strstart >= max_dist block_start_ -= (long) wsize; /* Slide the hash table (could be avoided with 32 bit values at the expense of memory usage). We slide even when level == 0 to keep the hash table consistent if we switch back to level > 0 later. (Using level 0 permanently is not an optimal usage of zlib, so we don't care about this pathological case.) */ n = hash_size_; p = &head_[n]; do { m = *--p; *p = (std::uint16_t)(m >= wsize ? m-wsize : 0); } while(--n); n = wsize; p = &prev_[n]; do { m = *--p; *p = (std::uint16_t)(m >= wsize ? m-wsize : 0); /* If n is not on any hash chain, prev[n] is garbage but its value will never be used. */ } while(--n); more += wsize; } if(zs.avail_in == 0) break; /* If there was no sliding: strstart <= WSIZE+max_dist-1 && lookahead <= kMinLookahead - 1 && more == window_size - lookahead - strstart => more >= window_size - (kMinLookahead-1 + WSIZE + max_dist-1) => more >= window_size - 2*WSIZE + 2 In the BIG_MEM or MMAP case (not yet supported), window_size == input_size + kMinLookahead && strstart + lookahead_ <= input_size => more >= kMinLookahead. Otherwise, window_size == 2*WSIZE so more >= 2. If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ n = read_buf(zs, window_ + strstart_ + lookahead_, more); lookahead_ += n; // Initialize the hash value now that we have some input: if(lookahead_ + insert_ >= minMatch) { uInt str = strstart_ - insert_; ins_h_ = window_[str]; update_hash(ins_h_, window_[str + 1]); while(insert_) { update_hash(ins_h_, window_[str + minMatch-1]); prev_[str & w_mask_] = head_[ins_h_]; head_[ins_h_] = (std::uint16_t)str; str++; insert_--; if(lookahead_ + insert_ < minMatch) break; } } /* If the whole input has less than minMatch bytes, ins_h is garbage, but this is not important since only literal bytes will be emitted. */ } while(lookahead_ < kMinLookahead && zs.avail_in != 0); /* If the kWinInit bytes after the end of the current data have never been written, then zero those bytes in order to avoid memory check reports of the use of uninitialized (or uninitialised as Julian writes) bytes by the longest match routines. Update the high water mark for the next time through here. kWinInit is set to maxMatch since the longest match routines allow scanning to strstart + maxMatch, ignoring lookahead. */ if(high_water_ < window_size_) { std::uint32_t curr = strstart_ + (std::uint32_t)(lookahead_); std::uint32_t winit; if(high_water_ < curr) { /* Previous high water mark below current data -- zero kWinInit bytes or up to end of window, whichever is less. */ winit = window_size_ - curr; if(winit > kWinInit) winit = kWinInit; std::memset(window_ + curr, 0, (unsigned)winit); high_water_ = curr + winit; } else if(high_water_ < (std::uint32_t)curr + kWinInit) { /* High water mark at or above current data, but below current data plus kWinInit -- zero out to current data plus kWinInit, or up to end of window, whichever is less. */ winit = (std::uint32_t)curr + kWinInit - high_water_; if(winit > window_size_ - high_water_) winit = window_size_ - high_water_; std::memset(window_ + high_water_, 0, (unsigned)winit); high_water_ += winit; } } } /* Flush as much pending output as possible. All write() output goes through this function so some applications may wish to modify it to avoid allocating a large strm->next_out buffer and copying into it. (See also read_buf()). */ void deflate_stream:: flush_pending(z_params& zs) { tr_flush_bits(); auto len = clamp(pending_, zs.avail_out); if(len == 0) return; std::memcpy(zs.next_out, pending_out_, len); zs.next_out = static_cast<std::uint8_t*>(zs.next_out) + len; pending_out_ += len; zs.total_out += len; zs.avail_out -= len; pending_ -= len; if(pending_ == 0) pending_out_ = pending_buf_; } /* Flush the current block, with given end-of-file flag. IN assertion: strstart is set to the end of the current match. */ void deflate_stream:: flush_block(z_params& zs, bool last) { tr_flush_block(zs, (block_start_ >= 0L ? (char *)&window_[(unsigned)block_start_] : (char *)0), (std::uint32_t)((long)strstart_ - block_start_), last); block_start_ = strstart_; flush_pending(zs); } /* Read a new buffer from the current input stream, update the adler32 and total number of bytes read. All write() input goes through this function so some applications may wish to modify it to avoid allocating a large strm->next_in buffer and copying from it. (See also flush_pending()). */ int deflate_stream:: read_buf(z_params& zs, Byte *buf, unsigned size) { auto len = clamp(zs.avail_in, size); if(len == 0) return 0; zs.avail_in -= len; std::memcpy(buf, zs.next_in, len); zs.next_in = static_cast< std::uint8_t const*>(zs.next_in) + len; zs.total_in += len; return (int)len; } /* Set match_start to the longest match starting at the given string and return its length. Matches shorter or equal to prev_length are discarded, in which case the result is equal to prev_length and match_start is garbage. IN assertions: cur_match is the head of the hash chain for the current string (strstart) and its distance is <= max_dist, and prev_length >= 1 OUT assertion: the match length is not greater than s->lookahead_. For 80x86 and 680x0, an optimized version will be provided in match.asm or match.S. The code will be functionally equivalent. */ uInt deflate_stream:: longest_match(IPos cur_match) { unsigned chain_length = max_chain_length_;/* max hash chain length */ Byte *scan = window_ + strstart_; /* current string */ Byte *match; /* matched string */ int len; /* length of current match */ int best_len = prev_length_; /* best match length so far */ int nice_match = nice_match_; /* stop if match long enough */ IPos limit = strstart_ > (IPos)max_dist() ? strstart_ - (IPos)max_dist() : 0; /* Stop when cur_match becomes <= limit. To simplify the code, * we prevent matches with the string of window index 0. */ std::uint16_t *prev = prev_; uInt wmask = w_mask_; Byte *strend = window_ + strstart_ + maxMatch; Byte scan_end1 = scan[best_len-1]; Byte scan_end = scan[best_len]; /* The code is optimized for HASH_BITS >= 8 and maxMatch-2 multiple of 16. * It is easy to get rid of this optimization if necessary. */ BOOST_ASSERT(hash_bits_ >= 8 && maxMatch == 258); /* Do not waste too much time if we already have a good match: */ if(prev_length_ >= good_match_) { chain_length >>= 2; } /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ if((uInt)nice_match > lookahead_) nice_match = lookahead_; BOOST_ASSERT((std::uint32_t)strstart_ <= window_size_-kMinLookahead); do { BOOST_ASSERT(cur_match < strstart_); match = window_ + cur_match; /* Skip to next match if the match length cannot increase * or if the match length is less than 2. Note that the checks below * for insufficient lookahead only occur occasionally for performance * reasons. Therefore uninitialized memory will be accessed, and * conditional jumps will be made that depend on those values. * However the length of the match is limited to the lookahead, so * the output of deflate is not affected by the uninitialized values. */ if( match[best_len] != scan_end || match[best_len-1] != scan_end1 || *match != *scan || *++match != scan[1]) continue; /* The check at best_len-1 can be removed because it will be made * again later. (This heuristic is not always a win.) * It is not necessary to compare scan[2] and match[2] since they * are always equal when the other bytes match, given that * the hash keys are equal and that HASH_BITS >= 8. */ scan += 2, match++; BOOST_ASSERT(*scan == *match); /* We check for insufficient lookahead only every 8th comparison; * the 256th check will be made at strstart+258. */ do { } while( *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && *++scan == *++match && scan < strend); BOOST_ASSERT(scan <= window_+(unsigned)(window_size_-1)); len = maxMatch - (int)(strend - scan); scan = strend - maxMatch; if(len > best_len) { match_start_ = cur_match; best_len = len; if(len >= nice_match) break; scan_end1 = scan[best_len-1]; scan_end = scan[best_len]; } } while((cur_match = prev[cur_match & wmask]) > limit && --chain_length != 0); if((uInt)best_len <= lookahead_) return (uInt)best_len; return lookahead_; } //------------------------------------------------------------------------------ /* Copy without compression as much as possible from the input stream, return the current block state. This function does not insert new strings in the dictionary since uncompressible data is probably not useful. This function is used only for the level=0 compression option. NOTE: this function should be optimized to avoid extra copying from window to pending_buf. */ auto deflate_stream:: f_stored(z_params& zs, Flush flush) -> block_state { /* Stored blocks are limited to 0xffff bytes, pending_buf is limited * to pending_buf_size, and each stored block has a 5 byte header: */ std::uint32_t max_block_size = 0xffff; std::uint32_t max_start; if(max_block_size > pending_buf_size_ - 5) { max_block_size = pending_buf_size_ - 5; } /* Copy as much as possible from input to output: */ for(;;) { /* Fill the window as much as possible: */ if(lookahead_ <= 1) { BOOST_ASSERT(strstart_ < w_size_+max_dist() || block_start_ >= (long)w_size_); fill_window(zs); if(lookahead_ == 0 && flush == Flush::none) return need_more; if(lookahead_ == 0) break; /* flush the current block */ } BOOST_ASSERT(block_start_ >= 0L); strstart_ += lookahead_; lookahead_ = 0; /* Emit a stored block if pending_buf will be full: */ max_start = block_start_ + max_block_size; if(strstart_ == 0 || (std::uint32_t)strstart_ >= max_start) { /* strstart == 0 is possible when wraparound on 16-bit machine */ lookahead_ = (uInt)(strstart_ - max_start); strstart_ = (uInt)max_start; flush_block(zs, false); if(zs.avail_out == 0) return need_more; } /* Flush if we may have to slide, otherwise block_start may become * negative and the data will be gone: */ if(strstart_ - (uInt)block_start_ >= max_dist()) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } } insert_ = 0; if(flush == Flush::finish) { flush_block(zs, true); if(zs.avail_out == 0) return finish_started; return finish_done; } if((long)strstart_ > block_start_) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } return block_done; } /* Compress as much as possible from the input stream, return the current block state. This function does not perform lazy evaluation of matches and inserts new strings in the dictionary only for unmatched strings or for short matches. It is used only for the fast compression options. */ auto deflate_stream:: f_fast(z_params& zs, Flush flush) -> block_state { IPos hash_head; /* head of the hash chain */ bool bflush; /* set if current block must be flushed */ for(;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need maxMatch bytes * for the next match, plus minMatch bytes to insert the * string following the next match. */ if(lookahead_ < kMinLookahead) { fill_window(zs); if(lookahead_ < kMinLookahead && flush == Flush::none) return need_more; if(lookahead_ == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = 0; if(lookahead_ >= minMatch) { insert_string(hash_head); } /* Find the longest match, discarding those <= prev_length. * At this point we have always match_length < minMatch */ if(hash_head != 0 && strstart_ - hash_head <= max_dist()) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ match_length_ = longest_match (hash_head); /* longest_match() sets match_start */ } if(match_length_ >= minMatch) { tr_tally_dist(static_cast<std::uint16_t>(strstart_ - match_start_), static_cast<std::uint8_t>(match_length_ - minMatch), bflush); lookahead_ -= match_length_; /* Insert new strings in the hash table only if the match length * is not too large. This saves time but degrades compression. */ if(match_length_ <= max_lazy_match_ && lookahead_ >= minMatch) { match_length_--; /* string at strstart already in table */ do { strstart_++; insert_string(hash_head); /* strstart never exceeds WSIZE-maxMatch, so there are * always minMatch bytes ahead. */ } while(--match_length_ != 0); strstart_++; } else { strstart_ += match_length_; match_length_ = 0; ins_h_ = window_[strstart_]; update_hash(ins_h_, window_[strstart_+1]); /* If lookahead < minMatch, ins_h is garbage, but it does not * matter since it will be recomputed at next deflate call. */ } } else { /* No match, output a literal byte */ tr_tally_lit(window_[strstart_], bflush); lookahead_--; strstart_++; } if(bflush) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } } insert_ = strstart_ < minMatch-1 ? strstart_ : minMatch-1; if(flush == Flush::finish) { flush_block(zs, true); if(zs.avail_out == 0) return finish_started; return finish_done; } if(last_lit_) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } return block_done; } /* Same as above, but achieves better compression. We use a lazy evaluation for matches: a match is finally adopted only if there is no better match at the next window position. */ auto deflate_stream:: f_slow(z_params& zs, Flush flush) -> block_state { IPos hash_head; /* head of hash chain */ bool bflush; /* set if current block must be flushed */ /* Process the input block. */ for(;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need maxMatch bytes * for the next match, plus minMatch bytes to insert the * string following the next match. */ if(lookahead_ < kMinLookahead) { fill_window(zs); if(lookahead_ < kMinLookahead && flush == Flush::none) return need_more; if(lookahead_ == 0) break; /* flush the current block */ } /* Insert the string window[strstart .. strstart+2] in the * dictionary, and set hash_head to the head of the hash chain: */ hash_head = 0; if(lookahead_ >= minMatch) insert_string(hash_head); /* Find the longest match, discarding those <= prev_length. */ prev_length_ = match_length_, prev_match_ = match_start_; match_length_ = minMatch-1; if(hash_head != 0 && prev_length_ < max_lazy_match_ && strstart_ - hash_head <= max_dist()) { /* To simplify the code, we prevent matches with the string * of window index 0 (in particular we have to avoid a match * of the string with itself at the start of the input file). */ match_length_ = longest_match(hash_head); /* longest_match() sets match_start */ if(match_length_ <= 5 && (strategy_ == Strategy::filtered || (match_length_ == minMatch && strstart_ - match_start_ > kTooFar) )) { /* If prev_match is also minMatch, match_start is garbage * but we will ignore the current match anyway. */ match_length_ = minMatch-1; } } /* If there was a match at the previous step and the current * match is not better, output the previous match: */ if(prev_length_ >= minMatch && match_length_ <= prev_length_) { /* Do not insert strings in hash table beyond this. */ uInt max_insert = strstart_ + lookahead_ - minMatch; tr_tally_dist( static_cast<std::uint16_t>(strstart_ -1 - prev_match_), static_cast<std::uint8_t>(prev_length_ - minMatch), bflush); /* Insert in hash table all strings up to the end of the match. * strstart-1 and strstart are already inserted. If there is not * enough lookahead, the last two strings are not inserted in * the hash table. */ lookahead_ -= prev_length_-1; prev_length_ -= 2; do { if(++strstart_ <= max_insert) insert_string(hash_head); } while(--prev_length_ != 0); match_available_ = 0; match_length_ = minMatch-1; strstart_++; if(bflush) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } } else if(match_available_) { /* If there was no match at the previous position, output a * single literal. If there was a match but the current match * is longer, truncate the previous match to a single literal. */ tr_tally_lit(window_[strstart_-1], bflush); if(bflush) flush_block(zs, false); strstart_++; lookahead_--; if(zs.avail_out == 0) return need_more; } else { /* There is no previous match to compare with, wait for * the next step to decide. */ match_available_ = 1; strstart_++; lookahead_--; } } BOOST_ASSERT(flush != Flush::none); if(match_available_) { tr_tally_lit(window_[strstart_-1], bflush); match_available_ = 0; } insert_ = strstart_ < minMatch-1 ? strstart_ : minMatch-1; if(flush == Flush::finish) { flush_block(zs, true); if(zs.avail_out == 0) return finish_started; return finish_done; } if(last_lit_) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } return block_done; } /* For Strategy::rle, simply look for runs of bytes, generate matches only of distance one. Do not maintain a hash table. (It will be regenerated if this run of deflate switches away from Strategy::rle.) */ auto deflate_stream:: f_rle(z_params& zs, Flush flush) -> block_state { bool bflush; // set if current block must be flushed uInt prev; // byte at distance one to match Byte *scan, *strend; // scan goes up to strend for length of run for(;;) { /* Make sure that we always have enough lookahead, except * at the end of the input file. We need maxMatch bytes * for the longest run, plus one for the unrolled loop. */ if(lookahead_ <= maxMatch) { fill_window(zs); if(lookahead_ <= maxMatch && flush == Flush::none) { return need_more; } if(lookahead_ == 0) break; /* flush the current block */ } /* See how many times the previous byte repeats */ match_length_ = 0; if(lookahead_ >= minMatch && strstart_ > 0) { scan = window_ + strstart_ - 1; prev = *scan; if(prev == *++scan && prev == *++scan && prev == *++scan) { strend = window_ + strstart_ + maxMatch; do { } while(prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); match_length_ = maxMatch - (int)(strend - scan); if(match_length_ > lookahead_) match_length_ = lookahead_; } BOOST_ASSERT(scan <= window_+(uInt)(window_size_-1)); } /* Emit match if have run of minMatch or longer, else emit literal */ if(match_length_ >= minMatch) { tr_tally_dist(std::uint16_t{1}, static_cast<std::uint8_t>(match_length_ - minMatch), bflush); lookahead_ -= match_length_; strstart_ += match_length_; match_length_ = 0; } else { /* No match, output a literal byte */ tr_tally_lit(window_[strstart_], bflush); lookahead_--; strstart_++; } if(bflush) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } } insert_ = 0; if(flush == Flush::finish) { flush_block(zs, true); if(zs.avail_out == 0) return finish_started; return finish_done; } if(last_lit_) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } return block_done; } /* =========================================================================== * For Strategy::huffman, do not look for matches. Do not maintain a hash table. * (It will be regenerated if this run of deflate switches away from Huffman.) */ auto deflate_stream:: f_huff(z_params& zs, Flush flush) -> block_state { bool bflush; // set if current block must be flushed for(;;) { // Make sure that we have a literal to write. if(lookahead_ == 0) { fill_window(zs); if(lookahead_ == 0) { if(flush == Flush::none) return need_more; break; // flush the current block } } // Output a literal byte match_length_ = 0; tr_tally_lit(window_[strstart_], bflush); lookahead_--; strstart_++; if(bflush) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } } insert_ = 0; if(flush == Flush::finish) { flush_block(zs, true); if(zs.avail_out == 0) return finish_started; return finish_done; } if(last_lit_) { flush_block(zs, false); if(zs.avail_out == 0) return need_more; } return block_done; } } // detail } // zlib } // beast } // boost #endif PK OP�[��G��f �f zlib/detail/deflate_stream.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_DETAIL_DEFLATE_STREAM_HPP #define BOOST_BEAST_ZLIB_DETAIL_DEFLATE_STREAM_HPP #include <boost/beast/zlib/error.hpp> #include <boost/beast/zlib/zlib.hpp> #include <boost/beast/zlib/detail/ranges.hpp> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/optional.hpp> #include <boost/throw_exception.hpp> #include <cstdint> #include <cstdlib> #include <cstring> #include <memory> #include <stdexcept> #include <type_traits> namespace boost { namespace beast { namespace zlib { namespace detail { class deflate_stream { protected: // Upper limit on code length static std::uint8_t constexpr maxBits = 15; // Number of length codes, not counting the special END_BLOCK code static std::uint16_t constexpr lengthCodes = 29; // Number of literal bytes 0..255 static std::uint16_t constexpr literals = 256; // Number of Literal or Length codes, including the END_BLOCK code static std::uint16_t constexpr lCodes = literals + 1 + lengthCodes; // Number of distance code lengths static std::uint16_t constexpr dCodes = 30; // Number of codes used to transfer the bit lengths static std::uint16_t constexpr blCodes = 19; // Number of distance codes static std::uint16_t constexpr distCodeLen = 512; // Size limit on bit length codes static std::uint8_t constexpr maxBlBits= 7; static std::uint16_t constexpr minMatch = 3; static std::uint16_t constexpr maxMatch = 258; // Can't change minMatch without also changing code, see original zlib BOOST_STATIC_ASSERT(minMatch == 3); // end of block literal code static std::uint16_t constexpr END_BLOCK = 256; // repeat previous bit length 3-6 times (2 bits of repeat count) static std::uint8_t constexpr REP_3_6 = 16; // repeat a zero length 3-10 times (3 bits of repeat count) static std::uint8_t constexpr REPZ_3_10 = 17; // repeat a zero length 11-138 times (7 bits of repeat count) static std::uint8_t constexpr REPZ_11_138 = 18; // The three kinds of block type static std::uint8_t constexpr STORED_BLOCK = 0; static std::uint8_t constexpr STATIC_TREES = 1; static std::uint8_t constexpr DYN_TREES = 2; // Maximum value for memLevel in deflateInit2 static std::uint8_t constexpr max_mem_level = 9; // Default memLevel static std::uint8_t constexpr DEF_MEM_LEVEL = max_mem_level; /* Note: the deflate() code requires max_lazy >= minMatch and max_chain >= 4 For deflate_fast() (levels <= 3) good is ignored and lazy has a different meaning. */ // maximum heap size static std::uint16_t constexpr HEAP_SIZE = 2 * lCodes + 1; // size of bit buffer in bi_buf static std::uint8_t constexpr Buf_size = 16; // Matches of length 3 are discarded if their distance exceeds kTooFar static std::size_t constexpr kTooFar = 4096; /* Minimum amount of lookahead, except at the end of the input file. See deflate.c for comments about the minMatch+1. */ static std::size_t constexpr kMinLookahead = maxMatch + minMatch+1; /* Number of bytes after end of data in window to initialize in order to avoid memory checker errors from longest match routines */ static std::size_t constexpr kWinInit = maxMatch; // Describes a single value and its code string. struct ct_data { std::uint16_t fc; // frequency count or bit string std::uint16_t dl; // parent node in tree or length of bit string bool operator==(ct_data const& rhs) const { return fc == rhs.fc && dl == rhs.dl; } }; struct static_desc { ct_data const* static_tree;// static tree or NULL std::uint8_t const* extra_bits; // extra bits for each code or NULL std::uint16_t extra_base; // base index for extra_bits std::uint16_t elems; // max number of elements in the tree std::uint8_t max_length; // max bit length for the codes }; struct lut_type { // Number of extra bits for each length code std::uint8_t const extra_lbits[lengthCodes] = { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0 }; // Number of extra bits for each distance code std::uint8_t const extra_dbits[dCodes] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; // Number of extra bits for each bit length code std::uint8_t const extra_blbits[blCodes] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7 }; // The lengths of the bit length codes are sent in order // of decreasing probability, to avoid transmitting the // lengths for unused bit length codes. std::uint8_t const bl_order[blCodes] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; ct_data ltree[lCodes + 2]; ct_data dtree[dCodes]; // Distance codes. The first 256 values correspond to the distances // 3 .. 258, the last 256 values correspond to the top 8 bits of // the 15 bit distances. std::uint8_t dist_code[distCodeLen]; std::uint8_t length_code[maxMatch-minMatch+1]; std::uint8_t base_length[lengthCodes]; std::uint16_t base_dist[dCodes]; static_desc l_desc = { ltree, extra_lbits, literals+1, lCodes, maxBits }; static_desc d_desc = { dtree, extra_dbits, 0, dCodes, maxBits }; static_desc bl_desc = { nullptr, extra_blbits, 0, blCodes, maxBlBits }; }; struct tree_desc { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ static_desc const* stat_desc; /* the corresponding static tree */ }; enum block_state { need_more, /* block not completed, need more input or more output */ block_done, /* block flush performed */ finish_started, /* finish started, need only more output at next deflate */ finish_done /* finish done, accept no more input or output */ }; // VFALCO This might not be needed, e.g. for zip/gzip enum StreamStatus { EXTRA_STATE = 69, NAME_STATE = 73, COMMENT_STATE = 91, HCRC_STATE = 103, BUSY_STATE = 113, FINISH_STATE = 666 }; /* A std::uint16_t is an index in the character window. We use short instead of int to * save space in the various tables. IPos is used only for parameter passing. */ using IPos = unsigned; using self = deflate_stream; typedef block_state(self::*compress_func)(z_params& zs, Flush flush); //-------------------------------------------------------------------------- lut_type const& lut_; bool inited_ = false; std::size_t buf_size_; std::unique_ptr<std::uint8_t[]> buf_; int status_; // as the name implies Byte* pending_buf_; // output still pending std::uint32_t pending_buf_size_; // size of pending_buf Byte* pending_out_; // next pending byte to output to the stream uInt pending_; // nb of bytes in the pending buffer boost::optional<Flush> last_flush_; // value of flush param for previous deflate call uInt w_size_; // LZ77 window size (32K by default) uInt w_bits_; // log2(w_size) (8..16) uInt w_mask_; // w_size - 1 /* Sliding window. Input bytes are read into the second half of the window, and move to the first half later to keep a dictionary of at least wSize bytes. With this organization, matches are limited to a distance of wSize-maxMatch bytes, but this ensures that IO is always performed with a length multiple of the block size. Also, it limits the window size to 64K. To do: use the user input buffer as sliding window. */ Byte *window_ = nullptr; /* Actual size of window: 2*wSize, except when the user input buffer is directly used as sliding window. */ std::uint32_t window_size_; /* Link to older string with same hash index. To limit the size of this array to 64K, this link is maintained only for the last 32K strings. An index in this array is thus a window index modulo 32K. */ std::uint16_t* prev_; std::uint16_t* head_; // Heads of the hash chains or 0 uInt ins_h_; // hash index of string to be inserted uInt hash_size_; // number of elements in hash table uInt hash_bits_; // log2(hash_size) uInt hash_mask_; // hash_size-1 /* Number of bits by which ins_h must be shifted at each input step. It must be such that after minMatch steps, the oldest byte no longer takes part in the hash key, that is: hash_shift * minMatch >= hash_bits */ uInt hash_shift_; /* Window position at the beginning of the current output block. Gets negative when the window is moved backwards. */ long block_start_; uInt match_length_; // length of best match IPos prev_match_; // previous match int match_available_; // set if previous match exists uInt strstart_; // start of string to insert uInt match_start_; // start of matching string uInt lookahead_; // number of valid bytes ahead in window /* Length of the best match at previous step. Matches not greater than this are discarded. This is used in the lazy match evaluation. */ uInt prev_length_; /* To speed up deflation, hash chains are never searched beyond this length. A higher limit improves compression ratio but degrades the speed. */ uInt max_chain_length_; /* Attempt to find a better match only when the current match is strictly smaller than this value. This mechanism is used only for compression levels >= 4. OR Insert new strings in the hash table only if the match length is not greater than this length. This saves time but degrades compression. used only for compression levels <= 3. */ uInt max_lazy_match_; int level_; // compression level (1..9) Strategy strategy_; // favor or force Huffman coding // Use a faster search when the previous match is longer than this uInt good_match_; int nice_match_; // Stop searching when current match exceeds this ct_data dyn_ltree_[ HEAP_SIZE]; // literal and length tree ct_data dyn_dtree_[ 2*dCodes+1]; // distance tree ct_data bl_tree_[ 2*blCodes+1]; // Huffman tree for bit lengths tree_desc l_desc_; // desc. for literal tree tree_desc d_desc_; // desc. for distance tree tree_desc bl_desc_; // desc. for bit length tree // number of codes at each bit length for an optimal tree std::uint16_t bl_count_[maxBits+1]; // Index within the heap array of least frequent node in the Huffman tree static std::size_t constexpr kSmallest = 1; /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. The same heap array is used to build all trees. */ int heap_[2*lCodes+1]; // heap used to build the Huffman trees int heap_len_; // number of elements in the heap int heap_max_; // element of largest frequency // Depth of each subtree used as tie breaker for trees of equal frequency std::uint8_t depth_[2*lCodes+1]; std::uint8_t *l_buf_; // buffer for literals or lengths /* Size of match buffer for literals/lengths. There are 4 reasons for limiting lit_bufsize to 64K: - frequencies can be kept in 16 bit counters - if compression is not successful for the first block, all input data is still in the window so we can still emit a stored block even when input comes from standard input. (This can also be done for all blocks if lit_bufsize is not greater than 32K.) - if compression is not successful for a file smaller than 64K, we can even emit a stored file instead of a stored block (saving 5 bytes). This is applicable only for zip (not gzip or zlib). - creating new Huffman trees less frequently may not provide fast adaptation to changes in the input data statistics. (Take for example a binary file with poorly compressible code followed by a highly compressible string table.) Smaller buffer sizes give fast adaptation but have of course the overhead of transmitting trees more frequently. - I can't count above 4 */ uInt lit_bufsize_; uInt last_lit_; // running index in l_buf_ /* Buffer for distances. To simplify the code, d_buf_ and l_buf_ have the same number of elements. To use different lengths, an extra flag array would be necessary. */ std::uint16_t* d_buf_; std::uint32_t opt_len_; // bit length of current block with optimal trees std::uint32_t static_len_; // bit length of current block with static trees uInt matches_; // number of string matches in current block uInt insert_; // bytes at end of window left to insert /* Output buffer. Bits are inserted starting at the bottom (least significant bits). */ std::uint16_t bi_buf_; /* Number of valid bits in bi_buf._ All bits above the last valid bit are always zero. */ int bi_valid_; /* High water mark offset in window for initialized bytes -- bytes above this are set to zero in order to avoid memory check warnings when longest match routines access bytes past the input. This is then updated to the new high water mark. */ std::uint32_t high_water_; //-------------------------------------------------------------------------- deflate_stream() : lut_(get_lut()) { } /* In order to simplify the code, particularly on 16 bit machines, match distances are limited to MAX_DIST instead of WSIZE. */ std::size_t max_dist() const { return w_size_ - kMinLookahead; } void put_byte(std::uint8_t c) { pending_buf_[pending_++] = c; } void put_short(std::uint16_t w) { put_byte(w & 0xff); put_byte(w >> 8); } /* Send a value on a given number of bits. IN assertion: length <= 16 and value fits in length bits. */ void send_bits(int value, int length) { if(bi_valid_ > (int)Buf_size - length) { bi_buf_ |= (std::uint16_t)value << bi_valid_; put_short(bi_buf_); bi_buf_ = (std::uint16_t)value >> (Buf_size - bi_valid_); bi_valid_ += length - Buf_size; } else { bi_buf_ |= (std::uint16_t)(value) << bi_valid_; bi_valid_ += length; } } // Send a code of the given tree void send_code(int value, ct_data const* tree) { send_bits(tree[value].fc, tree[value].dl); } /* Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used. */ std::uint8_t d_code(unsigned dist) { if(dist < 256) return lut_.dist_code[dist]; return lut_.dist_code[256+(dist>>7)]; } /* Update a hash value with the given input byte IN assertion: all calls to to update_hash are made with consecutive input characters, so that a running hash key can be computed from the previous key instead of complete recalculation each time. */ void update_hash(uInt& h, std::uint8_t c) { h = ((h << hash_shift_) ^ c) & hash_mask_; } /* Initialize the hash table (avoiding 64K overflow for 16 bit systems). prev[] will be initialized on the fly. */ void clear_hash() { head_[hash_size_-1] = 0; std::memset((Byte *)head_, 0, (unsigned)(hash_size_-1)*sizeof(*head_)); } /* Compares two subtrees, using the tree depth as tie breaker when the subtrees have equal frequency. This minimizes the worst case length. */ bool smaller(ct_data const* tree, int n, int m) { return tree[n].fc < tree[m].fc || (tree[n].fc == tree[m].fc && depth_[n] <= depth_[m]); } /* Insert string str in the dictionary and set match_head to the previous head of the hash chain (the most recent string with same hash key). Return the previous length of the hash chain. If this file is compiled with -DFASTEST, the compression level is forced to 1, and no hash chains are maintained. IN assertion: all calls to to INSERT_STRING are made with consecutive input characters and the first minMatch bytes of str are valid (except for the last minMatch-1 bytes of the input file). */ void insert_string(IPos& hash_head) { update_hash(ins_h_, window_[strstart_ + (minMatch-1)]); hash_head = prev_[strstart_ & w_mask_] = head_[ins_h_]; head_[ins_h_] = (std::uint16_t)strstart_; } //-------------------------------------------------------------------------- /* Values for max_lazy_match, good_match and max_chain_length, depending on * the desired pack level (0..9). The values given below have been tuned to * exclude worst case performance for pathological files. Better values may be * found for specific files. */ struct config { std::uint16_t good_length; /* reduce lazy search above this match length */ std::uint16_t max_lazy; /* do not perform lazy search above this match length */ std::uint16_t nice_length; /* quit search above this match length */ std::uint16_t max_chain; compress_func func; config( std::uint16_t good_length_, std::uint16_t max_lazy_, std::uint16_t nice_length_, std::uint16_t max_chain_, compress_func func_) : good_length(good_length_) , max_lazy(max_lazy_) , nice_length(nice_length_) , max_chain(max_chain_) , func(func_) { } }; static config get_config(std::size_t level) { switch(level) { // good lazy nice chain case 0: return { 0, 0, 0, 0, &self::deflate_stored}; // store only case 1: return { 4, 4, 8, 4, &self::deflate_fast}; // max speed, no lazy matches case 2: return { 4, 5, 16, 8, &self::deflate_fast}; case 3: return { 4, 6, 32, 32, &self::deflate_fast}; case 4: return { 4, 4, 16, 16, &self::deflate_slow}; // lazy matches case 5: return { 8, 16, 32, 32, &self::deflate_slow}; case 6: return { 8, 16, 128, 128, &self::deflate_slow}; case 7: return { 8, 32, 128, 256, &self::deflate_slow}; case 8: return { 32, 128, 258, 1024, &self::deflate_slow}; default: case 9: return { 32, 258, 258, 4096, &self::deflate_slow}; // max compression } } void maybe_init() { if(! inited_) init(); } template<class Unsigned> static Unsigned bi_reverse(Unsigned code, unsigned len); BOOST_BEAST_DECL static void gen_codes(ct_data *tree, int max_code, std::uint16_t *bl_count); BOOST_BEAST_DECL static lut_type const& get_lut(); BOOST_BEAST_DECL void doReset (int level, int windowBits, int memLevel, Strategy strategy); BOOST_BEAST_DECL void doReset (); BOOST_BEAST_DECL void doClear (); BOOST_BEAST_DECL std::size_t doUpperBound (std::size_t sourceLen) const; BOOST_BEAST_DECL void doTune (int good_length, int max_lazy, int nice_length, int max_chain); BOOST_BEAST_DECL void doParams (z_params& zs, int level, Strategy strategy, error_code& ec); BOOST_BEAST_DECL void doWrite (z_params& zs, boost::optional<Flush> flush, error_code& ec); BOOST_BEAST_DECL void doDictionary (Byte const* dict, uInt dictLength, error_code& ec); BOOST_BEAST_DECL void doPrime (int bits, int value, error_code& ec); BOOST_BEAST_DECL void doPending (unsigned* value, int* bits); BOOST_BEAST_DECL void init (); BOOST_BEAST_DECL void lm_init (); BOOST_BEAST_DECL void init_block (); BOOST_BEAST_DECL void pqdownheap (ct_data const* tree, int k); BOOST_BEAST_DECL void pqremove (ct_data const* tree, int& top); BOOST_BEAST_DECL void gen_bitlen (tree_desc *desc); BOOST_BEAST_DECL void build_tree (tree_desc *desc); BOOST_BEAST_DECL void scan_tree (ct_data *tree, int max_code); BOOST_BEAST_DECL void send_tree (ct_data *tree, int max_code); BOOST_BEAST_DECL int build_bl_tree (); BOOST_BEAST_DECL void send_all_trees (int lcodes, int dcodes, int blcodes); BOOST_BEAST_DECL void compress_block (ct_data const* ltree, ct_data const* dtree); BOOST_BEAST_DECL int detect_data_type (); BOOST_BEAST_DECL void bi_windup (); BOOST_BEAST_DECL void bi_flush (); BOOST_BEAST_DECL void copy_block (char *buf, unsigned len, int header); BOOST_BEAST_DECL void tr_init (); BOOST_BEAST_DECL void tr_align (); BOOST_BEAST_DECL void tr_flush_bits (); BOOST_BEAST_DECL void tr_stored_block (char *bu, std::uint32_t stored_len, int last); BOOST_BEAST_DECL void tr_tally_dist (std::uint16_t dist, std::uint8_t len, bool& flush); BOOST_BEAST_DECL void tr_tally_lit (std::uint8_t c, bool& flush); BOOST_BEAST_DECL void tr_flush_block (z_params& zs, char *buf, std::uint32_t stored_len, int last); BOOST_BEAST_DECL void fill_window (z_params& zs); BOOST_BEAST_DECL void flush_pending (z_params& zs); BOOST_BEAST_DECL void flush_block (z_params& zs, bool last); BOOST_BEAST_DECL int read_buf (z_params& zs, Byte *buf, unsigned size); BOOST_BEAST_DECL uInt longest_match (IPos cur_match); BOOST_BEAST_DECL block_state f_stored (z_params& zs, Flush flush); BOOST_BEAST_DECL block_state f_fast (z_params& zs, Flush flush); BOOST_BEAST_DECL block_state f_slow (z_params& zs, Flush flush); BOOST_BEAST_DECL block_state f_rle (z_params& zs, Flush flush); BOOST_BEAST_DECL block_state f_huff (z_params& zs, Flush flush); block_state deflate_stored(z_params& zs, Flush flush) { return f_stored(zs, flush); } block_state deflate_fast(z_params& zs, Flush flush) { return f_fast(zs, flush); } block_state deflate_slow(z_params& zs, Flush flush) { return f_slow(zs, flush); } block_state deflate_rle(z_params& zs, Flush flush) { return f_rle(zs, flush); } block_state deflate_huff(z_params& zs, Flush flush) { return f_huff(zs, flush); } }; //-------------------------------------------------------------------------- // Reverse the first len bits of a code template<class Unsigned> Unsigned deflate_stream:: bi_reverse(Unsigned code, unsigned len) { BOOST_STATIC_ASSERT(std::is_unsigned<Unsigned>::value); BOOST_ASSERT(len <= 8 * sizeof(unsigned)); Unsigned res = 0; do { res |= code & 1; code >>= 1; res <<= 1; } while(--len > 0); return res >> 1; } } // detail } // zlib } // beast } // boost #ifdef BOOST_BEAST_HEADER_ONLY #include <boost/beast/zlib/detail/deflate_stream.ipp> #endif #endif PK OP�[<�9��$ �$ zlib/detail/inflate_stream.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_DETAIL_INFLATE_STREAM_HPP #define BOOST_BEAST_ZLIB_DETAIL_INFLATE_STREAM_HPP #include <boost/beast/zlib/error.hpp> #include <boost/beast/zlib/zlib.hpp> #include <boost/beast/zlib/detail/bitstream.hpp> #include <boost/beast/zlib/detail/ranges.hpp> #include <boost/beast/zlib/detail/window.hpp> #if 0 #include <boost/beast/core/detail/type_traits.hpp> #include <boost/throw_exception.hpp> #include <algorithm> #include <array> #include <cstdint> #include <cstring> #include <stdexcept> #endif namespace boost { namespace beast { namespace zlib { namespace detail { class inflate_stream { protected: inflate_stream() { w_.reset(15); } BOOST_BEAST_DECL void doClear(); BOOST_BEAST_DECL void doReset(int windowBits); BOOST_BEAST_DECL void doWrite(z_params& zs, Flush flush, error_code& ec); void doReset() { doReset(w_.bits()); } private: enum Mode { HEAD, // i: waiting for magic header FLAGS, // i: waiting for method and flags (gzip) TIME, // i: waiting for modification time (gzip) OS, // i: waiting for extra flags and operating system (gzip) EXLEN, // i: waiting for extra length (gzip) EXTRA, // i: waiting for extra bytes (gzip) NAME, // i: waiting for end of file name (gzip) COMMENT, // i: waiting for end of comment (gzip) HCRC, // i: waiting for header crc (gzip) TYPE, // i: waiting for type bits, including last-flag bit TYPEDO, // i: same, but skip check to exit inflate on new block STORED, // i: waiting for stored size (length and complement) COPY_, // i/o: same as COPY below, but only first time in COPY, // i/o: waiting for input or output to copy stored block TABLE, // i: waiting for dynamic block table lengths LENLENS, // i: waiting for code length code lengths CODELENS, // i: waiting for length/lit and distance code lengths LEN_, // i: same as LEN below, but only first time in LEN, // i: waiting for length/lit/eob code LENEXT, // i: waiting for length extra bits DIST, // i: waiting for distance code DISTEXT,// i: waiting for distance extra bits MATCH, // o: waiting for output space to copy string LIT, // o: waiting for output space to write literal CHECK, // i: waiting for 32-bit check value LENGTH, // i: waiting for 32-bit length (gzip) DONE, // finished check, done -- remain here until reset BAD, // got a data error -- remain here until reset SYNC // looking for synchronization bytes to restart inflate() }; /* Structure for decoding tables. Each entry provides either the information needed to do the operation requested by the code that indexed that table entry, or it provides a pointer to another table that indexes more bits of the code. op indicates whether the entry is a pointer to another table, a literal, a length or distance, an end-of-block, or an invalid code. For a table pointer, the low four bits of op is the number of index bits of that table. For a length or distance, the low four bits of op is the number of extra bits to get after the code. bits is the number of bits in this code or part of the code to drop off of the bit buffer. val is the actual byte to output in the case of a literal, the base length or distance, or the offset from the current table to the next table. Each entry is four bytes. op values as set by inflate_table(): 00000000 - literal 0000tttt - table link, tttt != 0 is the number of table index bits 0001eeee - length or distance, eeee is the number of extra bits 01100000 - end of block 01000000 - invalid code */ struct code { std::uint8_t op; // operation, extra bits, table bits std::uint8_t bits; // bits in this part of the code std::uint16_t val; // offset in table or code value }; /* Maximum size of the dynamic table. The maximum number of code structures is 1444, which is the sum of 852 for literal/length codes and 592 for distance codes. These values were found by exhaustive searches using the program examples/enough.c found in the zlib distribtution. The arguments to that program are the number of symbols, the initial root table size, and the maximum bit length of a code. "enough 286 9 15" for literal/length codes returns returns 852, and "enough 30 6 15" for distance codes returns 592. The initial root table size (9 or 6) is found in the fifth argument of the inflate_table() calls in inflate.c and infback.c. If the root table size is changed, then these maximum sizes would be need to be recalculated and updated. */ static std::uint16_t constexpr kEnoughLens = 852; static std::uint16_t constexpr kEnoughDists = 592; static std::uint16_t constexpr kEnough = kEnoughLens + kEnoughDists; struct codes { code const* lencode; code const* distcode; unsigned lenbits; // VFALCO use std::uint8_t unsigned distbits; }; // Type of code to build for inflate_table() enum class build { codes, lens, dists }; BOOST_BEAST_DECL static void inflate_table( build type, std::uint16_t* lens, std::size_t codes, code** table, unsigned *bits, std::uint16_t* work, error_code& ec); BOOST_BEAST_DECL static codes const& get_fixed_tables(); BOOST_BEAST_DECL void fixedTables(); BOOST_BEAST_DECL void inflate_fast(ranges& r, error_code& ec); bitstream bi_; Mode mode_ = HEAD; // current inflate mode int last_ = 0; // true if processing last block unsigned dmax_ = 32768U; // zlib header max distance (INFLATE_STRICT) // sliding window window w_; // for string and stored block copying unsigned length_; // literal or length of data to copy unsigned offset_; // distance back to copy string from // for table and code decoding unsigned extra_; // extra bits needed // dynamic table building unsigned ncode_; // number of code length code lengths unsigned nlen_; // number of length code lengths unsigned ndist_; // number of distance code lengths unsigned have_; // number of code lengths in lens[] unsigned short lens_[320]; // temporary storage for code lengths unsigned short work_[288]; // work area for code table building code codes_[kEnough]; // space for code tables code *next_ = codes_; // next available space in codes[] int back_ = -1; // bits back of last unprocessed length/lit unsigned was_; // initial length of match // fixed and dynamic code tables code const* lencode_ = codes_ ; // starting table for length/literal codes code const* distcode_ = codes_; // starting table for distance codes unsigned lenbits_; // index bits for lencode unsigned distbits_; // index bits for distcode }; } // detail } // zlib } // beast } // boost #ifdef BOOST_BEAST_HEADER_ONLY #include <boost/beast/zlib/detail/inflate_stream.ipp> #endif #endif PK OP�[̔��e e zlib/detail/bitstream.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_DETAIL_BITSTREAM_HPP #define BOOST_BEAST_ZLIB_DETAIL_BITSTREAM_HPP #include <boost/assert.hpp> #include <cstdint> #include <iterator> namespace boost { namespace beast { namespace zlib { namespace detail { class bitstream { using value_type = std::uint32_t; value_type v_ = 0; unsigned n_ = 0; public: // returns the number of bits in the reservoir unsigned size() const { return n_; } // discard n bits void drop(std::size_t n) { BOOST_ASSERT(n <= n_); n_ -= static_cast<unsigned>(n); v_ >>= n; } // flush everything void flush() { n_ = 0; v_ = 0; } // flush to the next byte boundary void flush_byte() { drop(n_ % 8); } // ensure at least n bits template<class FwdIt> bool fill(std::size_t n, FwdIt& first, FwdIt const& last); // fill 8 bits, unchecked template<class FwdIt> void fill_8(FwdIt& it); // fill 16 bits, unchecked template<class FwdIt> void fill_16(FwdIt& it); // return n bits template<class Unsigned> void peek(Unsigned& value, std::size_t n); // return everything in the reservoir value_type peek_fast() const { return v_; } // return n bits, and consume template<class Unsigned> void read(Unsigned& value, std::size_t n); // rewind by the number of whole bytes stored (unchecked) template<class BidirIt> void rewind(BidirIt& it); }; template<class FwdIt> bool bitstream:: fill(std::size_t n, FwdIt& first, FwdIt const& last) { while(n_ < n) { if(first == last) return false; v_ += static_cast<value_type>(*first++) << n_; n_ += 8; } return true; } template<class FwdIt> void bitstream:: fill_8(FwdIt& it) { v_ += static_cast<value_type>(*it++) << n_; n_ += 8; } template<class FwdIt> void bitstream:: fill_16(FwdIt& it) { v_ += static_cast<value_type>(*it++) << n_; n_ += 8; v_ += static_cast<value_type>(*it++) << n_; n_ += 8; } template<class Unsigned> void bitstream:: peek(Unsigned& value, std::size_t n) { BOOST_ASSERT(n <= sizeof(value)*8); BOOST_ASSERT(n <= n_); value = static_cast<Unsigned>( v_ & ((1ULL << n) - 1)); } template<class Unsigned> void bitstream:: read(Unsigned& value, std::size_t n) { BOOST_ASSERT(n < sizeof(v_)*8); BOOST_ASSERT(n <= n_); value = static_cast<Unsigned>( v_ & ((1ULL << n) - 1)); v_ >>= n; n_ -= static_cast<unsigned>(n); } template<class BidirIt> void bitstream:: rewind(BidirIt& it) { auto len = n_ >> 3; it = std::prev(it, len); n_ &= 7; v_ &= (1U << n_) - 1; } } // detail } // zlib } // beast } // boost #endif PK OP�[�7!\� � zlib/detail/ranges.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_DETAIL_RANGES_HPP #define BOOST_BEAST_ZLIB_DETAIL_RANGES_HPP #include <cstdint> #include <type_traits> namespace boost { namespace beast { namespace zlib { namespace detail { struct ranges { template<bool isConst> struct range { using iter_t = typename std::conditional<isConst, std::uint8_t const*, std::uint8_t*>::type; iter_t first; iter_t last; iter_t next; // total bytes in range std::size_t size() const { return last - first; } // bytes consumed std::size_t used() const { return next - first; } // bytes remaining std::size_t avail() const { return last - next; } }; range<true> in; range<false> out; }; // Clamp u to v where u and v are different types template<class U, class V> U clamp(U u, V v) { if(u > v) u = static_cast<U>(v); return u; } } // detail } // zlib } // beast } // boost #endif PK OP�[��,? ,? zlib/deflate_stream.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_ZLIB_DEFLATE_STREAM_HPP #define BOOST_BEAST_ZLIB_DEFLATE_STREAM_HPP #include <boost/beast/core/detail/config.hpp> #include <boost/beast/zlib/error.hpp> #include <boost/beast/zlib/zlib.hpp> #include <boost/beast/zlib/detail/deflate_stream.hpp> #include <algorithm> #include <cstdlib> #include <cstdint> #include <cstring> #include <memory> namespace boost { namespace beast { namespace zlib { // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ /** Raw deflate compressor. This is a port of zlib's "deflate" functionality to C++. */ class deflate_stream : private detail::deflate_stream { public: /** Construct a default deflate stream. Upon construction, the stream settings will be set to these default values: @li `level = 6` @li `windowBits = 15` @li `memLevel = 8` @li `strategy = Strategy::normal` Although the stream is ready to be used immediately after construction, any required internal buffers are not dynamically allocated until needed. */ deflate_stream() { reset(6, 15, DEF_MEM_LEVEL, Strategy::normal); } /** Reset the stream and compression settings. This function initializes the stream to the specified compression settings. Although the stream is ready to be used immediately after a reset, any required internal buffers are not dynamically allocated until needed. @note Any unprocessed input or pending output from previous calls are discarded. */ void reset( int level, int windowBits, int memLevel, Strategy strategy) { doReset(level, windowBits, memLevel, strategy); } /** Reset the stream without deallocating memory. This function performs the equivalent of calling `clear` followed by `reset` with the same compression settings, without deallocating the internal buffers. @note Any unprocessed input or pending output from previous calls are discarded. */ void reset() { doReset(); } /** Clear the stream. This function resets the stream and frees all dynamically allocated internal buffers. The compression settings are left unchanged. @note Any unprocessed input or pending output from previous calls are discarded. */ void clear() { doClear(); } /** Returns the upper limit on the size of a compressed block. This function makes a conservative estimate of the maximum number of bytes needed to store the result of compressing a block of data based on the current compression level and strategy. @param sourceLen The size of the uncompressed data. @return The maximum number of resulting compressed bytes. */ std::size_t upper_bound(std::size_t sourceLen) const { return doUpperBound(sourceLen); } /** Fine tune internal compression parameters. Compression parameters should only be tuned by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code (ZLib) for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. */ void tune( int good_length, int max_lazy, int nice_length, int max_chain) { doTune(good_length, max_lazy, nice_length, max_chain); } /** Compress input and write output. This function compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. In each call, one or both of these actions are performed: @li Compress more input starting at `zs.next_in` and update `zs.next_in` and `zs.avail_in` accordingly. If not all input can be processed (because there is not enough room in the output buffer), `zs.next_in` and `zs.avail_in` are updated and processing will resume at this point for the next call. @li Provide more output starting at `zs.next_out` and update `zs.next_out` and `zs.avail_out` accordingly. This action is forced if the parameter flush is not `Flush::none`. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary (in interactive applications). Some output may be provided even if flush is not set. Before the call, the application must ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating `zs.avail_in` or `zs.avail_out` accordingly; `zs.avail_out` should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (`zs.avail_out == 0`), or after each call of `write`. If `write` returns no error with zero `zs.avail_out`, it must be called again after making room in the output buffer because there might be more output pending. Normally the parameter flush is set to `Flush::none`, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to `Flush::sync`, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. In particular `zs.avail_in` is zero after the call if enough output space has been provided before the call. Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by the four bytes `{ 0x00, 0x00 0xff 0xff }`. If flush is set to `Flush::partial`, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed code block. If flush is set to `Flush::block`, a deflate block is completed and emitted, as for `Flush::sync`, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to `Flush::full`, all output is flushed as with `Flush::sync`, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using `Flush::full` too often can seriously degrade compression. If `write` returns with `zs.avail_out == 0`, this function must be called again with the same value of the flush parameter and more output space (updated `zs.avail_out`), until the flush is complete (`write` returns with non-zero `zs.avail_out`). In the case of a `Flush::full`or `Flush::sync`, make sure that `zs.avail_out` is greater than six to avoid repeated flush markers due to `zs.avail_out == 0` on return. If the parameter flush is set to `Flush::finish`, pending input is processed, pending output is flushed and deflate returns the error `error::end_of_stream` if there was enough output space; if deflate returns with no error, this function must be called again with `Flush::finish` and more output space (updated `zs.avail_out`) but no more input data, until it returns the error `error::end_of_stream` or another error. After `write` has returned the `error::end_of_stream` error, the only possible operations on the stream are to reset or destroy. `Flush::finish` can be used immediately after initialization if all the compression is to be done in a single step. In this case, `zs.avail_out` must be at least value returned by `upper_bound` (see below). Then `write` is guaranteed to return the `error::end_of_stream` error. If not enough output space is provided, deflate will not return `error::end_of_stream`, and it must be called again as described above. `write` returns no error if some progress has been made (more input processed or more output produced), `error::end_of_stream` if all input has been consumed and all output has been produced (only when flush is set to `Flush::finish`), `error::stream_error` if the stream state was inconsistent (for example if `zs.next_in` or `zs.next_out` was `nullptr`), `error::need_buffers` if no progress is possible (for example `zs.avail_in` or `zs.avail_out` was zero). Note that `error::need_buffers` is not fatal, and `write` can be called again with more input and more output space to continue compressing. */ void write( z_params& zs, Flush flush, error_code& ec) { doWrite(zs, flush, ec); } /** Update the compression level and strategy. This function dynamically updates the compression level and compression strategy. The interpretation of level and strategy is as in @ref reset. This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression level is changed, the input available so far is compressed with the old level (and may be flushed); the new level will take effect only at the next call of @ref write. Before the call of `params`, the stream state must be set as for a call of @ref write, since the currently available input may have to be compressed and flushed. In particular, `zs.avail_out` must be non-zero. @return `Z_OK` if success, `Z_STREAM_ERROR` if the source stream state was inconsistent or if a parameter was invalid, `error::need_buffers` if `zs.avail_out` was zero. */ void params( z_params& zs, int level, Strategy strategy, error_code& ec) { doParams(zs, level, strategy, ec); } /** Return bits pending in the output. This function returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they await more bits to join them in order to fill out a full byte. If pending or bits are `nullptr`, then those values are not set. @return `Z_OK` if success, or `Z_STREAM_ERROR` if the source stream state was inconsistent. */ void pending(unsigned *value, int *bits) { doPending(value, bits); } /** Insert bits into the compressed output stream. This function inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first `write` call after an initialization. `bits` must be less than or equal to 16, and that many of the least significant bits of `value` will be inserted in the output. @return `error::need_buffers` if there was not enough room in the internal buffer to insert the bits. */ void prime(int bits, int value, error_code& ec) { return doPrime(bits, value, ec); } }; /** Returns the upper limit on the size of a compressed block. This function makes a conservative estimate of the maximum number of bytes needed to store the result of compressing a block of data. @param bytes The size of the uncompressed data. @return The maximum number of resulting compressed bytes. */ std::size_t deflate_upper_bound(std::size_t bytes); /* For the default windowBits of 15 and memLevel of 8, this function returns a close to exact, as well as small, upper bound on the compressed size. They are coded as constants here for a reason--if the #define's are changed, then this function needs to be changed as well. The return value for 15 and 8 only works for those exact settings. For any setting other than those defaults for windowBits and memLevel, the value returned is a conservative worst case for the maximum expansion resulting from using fixed blocks instead of stored blocks, which deflate can emit on compressed data for some combinations of the parameters. This function could be more sophisticated to provide closer upper bounds for every combination of windowBits and memLevel. But even the conservative upper bound of about 14% expansion does not seem onerous for output buffer allocation. */ inline std::size_t deflate_upper_bound(std::size_t bytes) { return bytes + ((bytes + 7) >> 3) + ((bytes + 63) >> 6) + 5 + 6; } } // zlib } // beast } // boost #endif PK OP�[䶔�) �) zlib/inflate_stream.hppnu �[��� // // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // // This is a derivative work based on Zlib, copyright below: /* Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef BOOST_BEAST_ZLIB_INFLATE_STREAM_HPP #define BOOST_BEAST_ZLIB_INFLATE_STREAM_HPP #include <boost/beast/core/detail/config.hpp> #include <boost/beast/zlib/detail/inflate_stream.hpp> namespace boost { namespace beast { namespace zlib { /** Raw deflate stream decompressor. This implements a raw deflate stream decompressor. The deflate protocol is a compression protocol described in "DEFLATE Compressed Data Format Specification version 1.3" located here: https://tools.ietf.org/html/rfc1951 The implementation is a refactored port to C++ of ZLib's "inflate". A more detailed description of ZLib is at http://zlib.net/. Compression can be done in a single step if the buffers are large enough (for example if an input file is memory mapped), or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. */ class inflate_stream : private detail::inflate_stream { public: /** Construct a raw deflate decompression stream. The window size is set to the default of 15 bits. */ inflate_stream() = default; /** Reset the stream. This puts the stream in a newly constructed state with the previously specified window size, but without de-allocating any dynamically created structures. */ void reset() { doReset(); } /** Reset the stream. This puts the stream in a newly constructed state with the specified window size, but without de-allocating any dynamically created structures. */ void reset(int windowBits) { doReset(windowBits); } /** Put the stream in a newly constructed state. All dynamically allocated memory is de-allocated. */ void clear() { doClear(); } /** Decompress input and produce output. This function decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. One or both of the following actions are performed: @li Decompress more input starting at `zs.next_in` and update `zs.next_in` and `zs.avail_in` accordingly. If not all input can be processed (because there is not enough room in the output buffer), `zs.next_in` is updated and processing will resume at this point for the next call. @li Provide more output starting at `zs.next_out` and update `zs.next_out` and `zs.avail_out` accordingly. `write` provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call, the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the values in `zs` accordingly. The application can consume the uncompressed output when it wants, for example when the output buffer is full (`zs.avail_out == 0`), or after each call. If `write` returns no error and with zero `zs.avail_out`, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter may be `Flush::none`, `Flush::sync`, `Flush::finish`, `Flush::block`, or `Flush::trees`. `Flush::sync` requests to flush as much output as possible to the output buffer. `Flush::block` requests to stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause `write` to return immediately after the header and before the first block. When doing a raw inflate, `write` will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The `Flush::block` option assists in appending to or combining deflate streams. Also to assist in this, on return `write` will set `zs.data_type` to the number of unused bits in the last byte taken from `zs.next_in`, plus 64 if `write` is currently decoding the last block in the deflate stream, plus 128 if `write` returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to `zs.next_out`. The number of unused bits may in general be greater than seven, except when bit 7 of `zs.data_type` is set, in which case the number of unused bits will be less than eight. `zs.data_type` is set as noted here every time `write` returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The `Flush::trees` option behaves as `Flush::block` does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of `zs.data_type` when `write` returns immediately after reaching the end of the deflate block header. `write` should normally be called until it returns `error::end_of_stream` or another error. However if all decompression is to be performed in a single step (a single call of `write`), the parameter flush should be set to `Flush::finish`. In this case all pending input is processed and all pending output is flushed; `zs.avail_out` must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The use of `Flush::finish` is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single call. `Flush::finish` also informs inflate to not maintain a sliding window if the stream completes, which reduces inflate's memory footprint. If the stream does not complete, either because not all of the stream is provided or not enough output space is provided, then a sliding window will be allocated and `write` can be called again to continue the operation as if `Flush::none` had been used. In this implementation, `write` always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the effects of the flush parameter in this implementation are on the return value of `write` as noted below, when `write` returns early when `Flush::block` or `Flush::trees` is used, and when `write` avoids the allocation of memory for a sliding window when `Flush::finish` is used. If a preset dictionary is needed after this call, `write` sets `zs.adler` to the Adler-32 checksum of the dictionary chosen by the compressor and returns `error::need_dictionary`; otherwise it sets `zs.adler` to the Adler-32 checksum of all output produced so far (that is, `zs.total_out bytes`) and returns no error, `error::end_of_stream`, or an error code as described below. At the end of the stream, `write` checks that its computed adler32 checksum is equal to that saved by the compressor and returns `error::end_of_stream` only if the checksum is correct. This function returns no error if some progress has been made (more input processed or more output produced), `error::end_of_stream` if the end of the compressed data has been reached and all uncompressed output has been produced, `error::need_dictionary` if a preset dictionary is needed at this point, `error::invalid_data` if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value), `error::stream_error` if the stream structure was inconsistent (for example if `zs.next_in` or `zs.next_out` was null), `error::need_buffers` if no progress is possible or if there was not enough room in the output buffer when `Flush::finish` is used. Note that `error::need_buffers` is not fatal, and `write` can be called again with more input and more output space to continue decompressing. */ void write(z_params& zs, Flush flush, error_code& ec) { doWrite(zs, flush, ec); } }; } // zlib } // beast } // boost #endif PK OP�[�b� � &