| // Copyright 2016 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #ifndef BAZEL_SRC_TOOLS_SINGLEJAR_ZLIB_INTERFACE_H_ |
| #define BAZEL_SRC_TOOLS_SINGLEJAR_ZLIB_INTERFACE_H_ |
| |
| #include <cinttypes> |
| |
| #include "src/tools/singlejar/diag.h" |
| #include <zlib.h> |
| |
| // An interface to zlib's inflater. Usage: |
| // Inflater inflater; |
| // inflater.DataToInflate(data, data_size); |
| // for (;;) { |
| // int rc = inflater.Inflate(out_buffer, out_buffer_size); |
| // if (rc == Z_STREAM_END) { |
| // break; |
| // } |
| // // If we ran out of out_buffer, create a new one |
| // } |
| // inflater.reset(); |
| // NOTE that the sizes of the input/output buffers in zlib are 32-bit entities. |
| // Call Inflater::DataToInflate multiple times if 'data_size' in the usage |
| // example exceeds 4GB-1. |
| class Inflater { |
| public: |
| Inflater() { |
| zstream_.zalloc = Z_NULL; |
| zstream_.zfree = Z_NULL; |
| zstream_.opaque = Z_NULL; |
| zstream_.avail_in = 0; |
| zstream_.next_in = nullptr; |
| int ret = inflateInit2(&zstream_, -MAX_WBITS); |
| if (ret != Z_OK) { |
| diag_errx(2, "inflateInit2 returned %d\n", ret); |
| } |
| } |
| |
| ~Inflater() { inflateEnd(&zstream_); } |
| |
| void reset() { inflateReset(&zstream_); } |
| |
| void DataToInflate(const uint8_t *in_buffer, uint32_t in_buffer_length) { |
| zstream_.next_in = const_cast<uint8_t *>(in_buffer); |
| zstream_.avail_in = in_buffer_length; |
| } |
| |
| int Inflate(uint8_t *out_buffer, uint32_t out_buffer_length) { |
| zstream_.next_out = out_buffer; |
| zstream_.avail_out = out_buffer_length; |
| return inflate(&zstream_, Z_SYNC_FLUSH); |
| } |
| |
| const uint8_t *next_in() const { return zstream_.next_in; } |
| uint64_t total_in() const { return zstream_.total_in; } |
| |
| uint32_t available_out() const { return zstream_.avail_out; } |
| uint64_t total_out() const { return zstream_.total_out; } |
| |
| const char *error_message() const { return zstream_.msg; } |
| |
| private: |
| z_stream zstream_; |
| }; |
| |
| // A little wrapper around zlib's deflater. |
| // NOTE that the size of the data to inflate by a single call cannot exceed |
| // 4GB-1. |
| struct Deflater : z_stream { |
| Deflater() { |
| zalloc = Z_NULL; |
| zfree = Z_NULL; |
| opaque = Z_NULL; |
| next_in = nullptr; |
| avail_in = 0; |
| next_out = nullptr; |
| avail_out = 0; |
| int ret = deflateInit2(this, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, |
| 8, Z_DEFAULT_STRATEGY); |
| if (ret != Z_OK) { |
| diag_errx(2, "deflateInit returned %d (%s)", ret, msg); |
| } |
| } |
| |
| ~Deflater() { deflateEnd(this); } |
| |
| int Deflate(const uint8_t *data, uint32_t data_size, int flag) { |
| next_in = const_cast<uint8_t *>(data); |
| avail_in = data_size; |
| return deflate(this, flag); |
| } |
| }; |
| |
| #endif // BAZEL_SRC_TOOLS_SINGLEJAR_ZLIB_INTERFACE_H_ |