Commit 8549d411 authored by Sam Maier's avatar Sam Maier Committed by Commit Bot

Adding support for remaining deflate wrappers (zlib | raw) to

compression_utils_portable

This allows client code to select the wrapper format used which may be
faster (e.g. zlib format on older ARMv7 and early ARMv8 SoCs) depending
on the application.

The wrapper format selection code was partially taken from
zlib_bench.cc.

Bug: 833361
Change-Id: I8a317e6abc8bd2d66f2e940406badfd7e930e809
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1904505Reviewed-by: default avatarAdenilson Cavalcanti <cavalcantii@chromium.org>
Commit-Queue: Adenilson Cavalcanti <cavalcantii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713870}
parent 867a63b2
......@@ -42,7 +42,7 @@ bool GzipCompress(base::StringPiece input, std::string* output) {
const uLongf input_size = static_cast<uLongf>(input.size());
uLongf compressed_data_size =
zlib_internal::GZipExpectedCompressedSize(input_size);
zlib_internal::GzipExpectedCompressedSize(input_size);
Bytef* compressed_data;
if (!base::UncheckedMalloc(compressed_data_size,
......@@ -109,7 +109,7 @@ bool GzipUncompress(base::StringPiece input, std::string* output) {
}
uint32_t GetUncompressedSize(base::StringPiece compressed_data) {
return zlib_internal::GetUncompressedSize(
return zlib_internal::GetGzipUncompressedSize(
bit_cast<Bytef*>(compressed_data.data()), compressed_data.length());
}
......
......@@ -28,13 +28,13 @@ const int kZlibMemoryLevel = 8;
// The expected compressed size is based on the input size factored by
// internal Zlib constants (e.g. window size, etc) plus the wrapper
// header size.
uLongf GZipExpectedCompressedSize(uLongf input_size) {
uLongf GzipExpectedCompressedSize(uLongf input_size) {
return kGzipZlibHeaderDifferenceBytes + compressBound(input_size);
}
// The expected decompressed size is stored in the last
// 4 bytes of |input| in LE.
uint32_t GetUncompressedSize(const Bytef* compressed_data, size_t length) {
// 4 bytes of |input| in LE. See https://tools.ietf.org/html/rfc1952#page-5
uint32_t GetGzipUncompressedSize(const Bytef* compressed_data, size_t length) {
uint32_t size;
if (length < sizeof(size))
return 0;
......@@ -47,15 +47,39 @@ uint32_t GetUncompressedSize(const Bytef* compressed_data, size_t length) {
#endif
}
// This code is taken almost verbatim from third_party/zlib/compress.c. The only
// difference is deflateInit2() is called which sets the window bits to be > 16.
// That causes a gzip header to be emitted rather than a zlib header.
// The number of window bits determines the type of wrapper to use - see
// https://cs.chromium.org/chromium/src/third_party/zlib/zlib.h?l=566
inline int ZlibStreamWrapperType(WrapperType type) {
if (type == ZLIB) // zlib DEFLATE stream wrapper
return MAX_WBITS;
if (type == GZIP) // gzip DEFLATE stream wrapper
return MAX_WBITS + kWindowBitsToGetGzipHeader;
if (type == ZRAW) // no wrapper, use raw DEFLATE
return -MAX_WBITS;
return 0;
}
int GzipCompressHelper(Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length,
void* (*malloc_fn)(size_t),
void (*free_fn)(void*)) {
return CompressHelper(GZIP, dest, dest_length, source, source_length,
malloc_fn, free_fn);
}
// This code is taken almost verbatim from third_party/zlib/compress.c. The only
// difference is deflateInit2() is called which allows different window bits to
// be set. > 16 causes a gzip header to be emitted rather than a zlib header,
// and negative causes no header to emitted.
int CompressHelper(WrapperType wrapper_type,
Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length,
void* (*malloc_fn)(size_t),
void (*free_fn)(void*)) {
z_stream stream;
// FIXME(cavalcantii): z_const is not defined as 'const'.
......@@ -94,17 +118,21 @@ int GzipCompressHelper(Bytef* dest,
stream.opaque = static_cast<voidpf>(0);
}
gz_header gzip_header;
memset(&gzip_header, 0, sizeof(gzip_header));
int err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
MAX_WBITS + kWindowBitsToGetGzipHeader,
kZlibMemoryLevel, Z_DEFAULT_STRATEGY);
ZlibStreamWrapperType(wrapper_type), kZlibMemoryLevel,
Z_DEFAULT_STRATEGY);
if (err != Z_OK)
return err;
// This has to exist outside of the if statement to prevent it going off the
// stack before deflate(), which will use this object.
gz_header gzip_header;
if (wrapper_type == GZIP) {
memset(&gzip_header, 0, sizeof(gzip_header));
err = deflateSetHeader(&stream, &gzip_header);
if (err != Z_OK)
return err;
}
err = deflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
......@@ -117,13 +145,22 @@ int GzipCompressHelper(Bytef* dest,
return err;
}
// This code is taken almost verbatim from third_party/zlib/uncompr.c. The only
// difference is inflateInit2() is called which sets the window bits to be > 16.
// That causes a gzip header to be parsed rather than a zlib header.
int GzipUncompressHelper(Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length) {
return UncompressHelper(GZIP, dest, dest_length, source, source_length);
}
// This code is taken almost verbatim from third_party/zlib/uncompr.c. The only
// difference is inflateInit2() is called which allows different window bits to
// be set. > 16 causes a gzip header to be emitted rather than a zlib header,
// and negative causes no header to emitted.
int UncompressHelper(WrapperType wrapper_type,
Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length) {
z_stream stream;
// FIXME(cavalcantii): z_const is not defined as 'const'.
......@@ -140,7 +177,7 @@ int GzipUncompressHelper(Bytef* dest,
stream.zalloc = static_cast<alloc_func>(0);
stream.zfree = static_cast<free_func>(0);
int err = inflateInit2(&stream, MAX_WBITS + kWindowBitsToGetGzipHeader);
int err = inflateInit2(&stream, ZlibStreamWrapperType(wrapper_type));
if (err != Z_OK)
return err;
......
......@@ -17,9 +17,15 @@
namespace zlib_internal {
uLongf GZipExpectedCompressedSize(uLongf input_size);
enum WrapperType {
ZLIB,
GZIP,
ZRAW,
};
uint32_t GetUncompressedSize(const Bytef* compressed_data, size_t length);
uLongf GzipExpectedCompressedSize(uLongf input_size);
uint32_t GetGzipUncompressedSize(const Bytef* compressed_data, size_t length);
int GzipCompressHelper(Bytef* dest,
uLongf* dest_length,
......@@ -28,11 +34,25 @@ int GzipCompressHelper(Bytef* dest,
void* (*malloc_fn)(size_t),
void (*free_fn)(void*));
int CompressHelper(WrapperType wrapper_type,
Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length,
void* (*malloc_fn)(size_t),
void (*free_fn)(void*));
int GzipUncompressHelper(Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length);
int UncompressHelper(WrapperType wrapper_type,
Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length);
} // namespace zlib_internal
#endif // THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment