summaryrefslogtreecommitdiff
path: root/boost/beast/zlib/deflate_stream.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/beast/zlib/deflate_stream.hpp')
-rw-r--r--boost/beast/zlib/deflate_stream.hpp404
1 files changed, 404 insertions, 0 deletions
diff --git a/boost/beast/zlib/deflate_stream.hpp b/boost/beast/zlib/deflate_stream.hpp
new file mode 100644
index 0000000000..f57a0a5042
--- /dev/null
+++ b/boost/beast/zlib/deflate_stream.hpp
@@ -0,0 +1,404 @@
+//
+// Copyright (c) 2016-2017 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