|  | // 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_ |