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) { ...@@ -42,7 +42,7 @@ bool GzipCompress(base::StringPiece input, std::string* output) {
const uLongf input_size = static_cast<uLongf>(input.size()); const uLongf input_size = static_cast<uLongf>(input.size());
uLongf compressed_data_size = uLongf compressed_data_size =
zlib_internal::GZipExpectedCompressedSize(input_size); zlib_internal::GzipExpectedCompressedSize(input_size);
Bytef* compressed_data; Bytef* compressed_data;
if (!base::UncheckedMalloc(compressed_data_size, if (!base::UncheckedMalloc(compressed_data_size,
...@@ -109,7 +109,7 @@ bool GzipUncompress(base::StringPiece input, std::string* output) { ...@@ -109,7 +109,7 @@ bool GzipUncompress(base::StringPiece input, std::string* output) {
} }
uint32_t GetUncompressedSize(base::StringPiece compressed_data) { uint32_t GetUncompressedSize(base::StringPiece compressed_data) {
return zlib_internal::GetUncompressedSize( return zlib_internal::GetGzipUncompressedSize(
bit_cast<Bytef*>(compressed_data.data()), compressed_data.length()); bit_cast<Bytef*>(compressed_data.data()), compressed_data.length());
} }
......
...@@ -28,13 +28,13 @@ const int kZlibMemoryLevel = 8; ...@@ -28,13 +28,13 @@ const int kZlibMemoryLevel = 8;
// The expected compressed size is based on the input size factored by // The expected compressed size is based on the input size factored by
// internal Zlib constants (e.g. window size, etc) plus the wrapper // internal Zlib constants (e.g. window size, etc) plus the wrapper
// header size. // header size.
uLongf GZipExpectedCompressedSize(uLongf input_size) { uLongf GzipExpectedCompressedSize(uLongf input_size) {
return kGzipZlibHeaderDifferenceBytes + compressBound(input_size); return kGzipZlibHeaderDifferenceBytes + compressBound(input_size);
} }
// The expected decompressed size is stored in the last // The expected decompressed size is stored in the last
// 4 bytes of |input| in LE. // 4 bytes of |input| in LE. See https://tools.ietf.org/html/rfc1952#page-5
uint32_t GetUncompressedSize(const Bytef* compressed_data, size_t length) { uint32_t GetGzipUncompressedSize(const Bytef* compressed_data, size_t length) {
uint32_t size; uint32_t size;
if (length < sizeof(size)) if (length < sizeof(size))
return 0; return 0;
...@@ -47,15 +47,39 @@ uint32_t GetUncompressedSize(const Bytef* compressed_data, size_t length) { ...@@ -47,15 +47,39 @@ uint32_t GetUncompressedSize(const Bytef* compressed_data, size_t length) {
#endif #endif
} }
// This code is taken almost verbatim from third_party/zlib/compress.c. The only // The number of window bits determines the type of wrapper to use - see
// difference is deflateInit2() is called which sets the window bits to be > 16. // https://cs.chromium.org/chromium/src/third_party/zlib/zlib.h?l=566
// That causes a gzip header to be emitted rather than a zlib header. 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, int GzipCompressHelper(Bytef* dest,
uLongf* dest_length, uLongf* dest_length,
const Bytef* source, const Bytef* source,
uLong source_length, uLong source_length,
void* (*malloc_fn)(size_t), void* (*malloc_fn)(size_t),
void (*free_fn)(void*)) { 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; z_stream stream;
// FIXME(cavalcantii): z_const is not defined as 'const'. // FIXME(cavalcantii): z_const is not defined as 'const'.
...@@ -94,17 +118,21 @@ int GzipCompressHelper(Bytef* dest, ...@@ -94,17 +118,21 @@ int GzipCompressHelper(Bytef* dest,
stream.opaque = static_cast<voidpf>(0); 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, int err = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
MAX_WBITS + kWindowBitsToGetGzipHeader, ZlibStreamWrapperType(wrapper_type), kZlibMemoryLevel,
kZlibMemoryLevel, Z_DEFAULT_STRATEGY); Z_DEFAULT_STRATEGY);
if (err != Z_OK) if (err != Z_OK)
return err; return err;
err = deflateSetHeader(&stream, &gzip_header); // This has to exist outside of the if statement to prevent it going off the
if (err != Z_OK) // stack before deflate(), which will use this object.
return err; 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); err = deflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) { if (err != Z_STREAM_END) {
...@@ -117,13 +145,22 @@ int GzipCompressHelper(Bytef* dest, ...@@ -117,13 +145,22 @@ int GzipCompressHelper(Bytef* dest,
return err; 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, int GzipUncompressHelper(Bytef* dest,
uLongf* dest_length, uLongf* dest_length,
const Bytef* source, const Bytef* source,
uLong source_length) { 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; z_stream stream;
// FIXME(cavalcantii): z_const is not defined as 'const'. // FIXME(cavalcantii): z_const is not defined as 'const'.
...@@ -140,7 +177,7 @@ int GzipUncompressHelper(Bytef* dest, ...@@ -140,7 +177,7 @@ int GzipUncompressHelper(Bytef* dest,
stream.zalloc = static_cast<alloc_func>(0); stream.zalloc = static_cast<alloc_func>(0);
stream.zfree = static_cast<free_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) if (err != Z_OK)
return err; return err;
......
...@@ -17,9 +17,15 @@ ...@@ -17,9 +17,15 @@
namespace zlib_internal { 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, int GzipCompressHelper(Bytef* dest,
uLongf* dest_length, uLongf* dest_length,
...@@ -28,11 +34,25 @@ int GzipCompressHelper(Bytef* dest, ...@@ -28,11 +34,25 @@ int GzipCompressHelper(Bytef* dest,
void* (*malloc_fn)(size_t), void* (*malloc_fn)(size_t),
void (*free_fn)(void*)); 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, int GzipUncompressHelper(Bytef* dest,
uLongf* dest_length, uLongf* dest_length,
const Bytef* source, const Bytef* source,
uLong source_length); uLong source_length);
int UncompressHelper(WrapperType wrapper_type,
Bytef* dest,
uLongf* dest_length,
const Bytef* source,
uLong source_length);
} // namespace zlib_internal } // namespace zlib_internal
#endif // THIRD_PARTY_ZLIB_GOOGLE_COMPRESSION_UTILS_PORTABLE_H_ #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