1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 // Author: brianolson@google.com (Brian Olson) 9 // 10 // This file contains the definition for classes GzipInputStream and 11 // GzipOutputStream. 12 // 13 // GzipInputStream decompresses data from an underlying 14 // ZeroCopyInputStream and provides the decompressed data as a 15 // ZeroCopyInputStream. 16 // 17 // GzipOutputStream is an ZeroCopyOutputStream that compresses data to 18 // an underlying ZeroCopyOutputStream. 19 20 #ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ 21 #define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ 22 23 #include "google/protobuf/stubs/common.h" 24 #include "google/protobuf/io/zero_copy_stream.h" 25 #include "google/protobuf/port.h" 26 #include <zlib.h> 27 28 // Must be included last. 29 #include "google/protobuf/port_def.inc" 30 31 namespace google { 32 namespace protobuf { 33 namespace io { 34 35 // A ZeroCopyInputStream that reads compressed data through zlib 36 class PROTOBUF_EXPORT GzipInputStream final : public ZeroCopyInputStream { 37 public: 38 // Format key for constructor 39 enum Format { 40 // zlib will autodetect gzip header or deflate stream 41 AUTO = 0, 42 43 // GZIP streams have some extra header data for file attributes. 44 GZIP = 1, 45 46 // Simpler zlib stream format. 47 ZLIB = 2, 48 }; 49 50 // buffer_size and format may be -1 for default of 64kB and GZIP format 51 explicit GzipInputStream(ZeroCopyInputStream* sub_stream, 52 Format format = AUTO, int buffer_size = -1); 53 GzipInputStream(const GzipInputStream&) = delete; 54 GzipInputStream& operator=(const GzipInputStream&) = delete; 55 ~GzipInputStream() override; 56 57 // Return last error message or NULL if no error. ZlibErrorMessage()58 inline const char* ZlibErrorMessage() const { return zcontext_.msg; } ZlibErrorCode()59 inline int ZlibErrorCode() const { return zerror_; } 60 61 // implements ZeroCopyInputStream ---------------------------------- 62 bool Next(const void** data, int* size) override; 63 void BackUp(int count) override; 64 bool Skip(int count) override; 65 int64_t ByteCount() const override; 66 67 private: 68 Format format_; 69 70 ZeroCopyInputStream* sub_stream_; 71 72 z_stream zcontext_; 73 int zerror_; 74 75 void* output_buffer_; 76 void* output_position_; 77 size_t output_buffer_length_; 78 int64_t byte_count_; 79 80 int Inflate(int flush); 81 void DoNextOutput(const void** data, int* size); 82 }; 83 84 class PROTOBUF_EXPORT GzipOutputStream final : public ZeroCopyOutputStream { 85 public: 86 // Format key for constructor 87 enum Format { 88 // GZIP streams have some extra header data for file attributes. 89 GZIP = 1, 90 91 // Simpler zlib stream format. 92 ZLIB = 2, 93 }; 94 95 struct PROTOBUF_EXPORT Options { 96 // Defaults to GZIP. 97 Format format; 98 99 // What size buffer to use internally. Defaults to 64kB. 100 int buffer_size; 101 102 // A number between 0 and 9, where 0 is no compression and 9 is best 103 // compression. Defaults to Z_DEFAULT_COMPRESSION (see zlib.h). 104 int compression_level; 105 106 // Defaults to Z_DEFAULT_STRATEGY. Can also be set to Z_FILTERED, 107 // Z_HUFFMAN_ONLY, or Z_RLE. See the documentation for deflateInit2 in 108 // zlib.h for definitions of these constants. 109 int compression_strategy; 110 111 Options(); // Initializes with default values. 112 }; 113 114 // Create a GzipOutputStream with default options. 115 explicit GzipOutputStream(ZeroCopyOutputStream* sub_stream); 116 117 // Create a GzipOutputStream with the given options. 118 GzipOutputStream(ZeroCopyOutputStream* sub_stream, const Options& options); 119 GzipOutputStream(const GzipOutputStream&) = delete; 120 GzipOutputStream& operator=(const GzipOutputStream&) = delete; 121 122 ~GzipOutputStream() override; 123 124 // Return last error message or NULL if no error. ZlibErrorMessage()125 inline const char* ZlibErrorMessage() const { return zcontext_.msg; } ZlibErrorCode()126 inline int ZlibErrorCode() const { return zerror_; } 127 128 // Flushes data written so far to zipped data in the underlying stream. 129 // It is the caller's responsibility to flush the underlying stream if 130 // necessary. 131 // Compression may be less efficient stopping and starting around flushes. 132 // Returns true if no error. 133 // 134 // Please ensure that block size is > 6. Here is an excerpt from the zlib 135 // doc that explains why: 136 // 137 // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out 138 // is greater than six to avoid repeated flush markers due to 139 // avail_out == 0 on return. 140 bool Flush(); 141 142 // Writes out all data and closes the gzip stream. 143 // It is the caller's responsibility to close the underlying stream if 144 // necessary. 145 // Returns true if no error. 146 bool Close(); 147 148 // implements ZeroCopyOutputStream --------------------------------- 149 bool Next(void** data, int* size) override; 150 void BackUp(int count) override; 151 int64_t ByteCount() const override; 152 153 private: 154 ZeroCopyOutputStream* sub_stream_; 155 // Result from calling Next() on sub_stream_ 156 void* sub_data_; 157 int sub_data_size_; 158 159 z_stream zcontext_; 160 int zerror_; 161 void* input_buffer_; 162 size_t input_buffer_length_; 163 164 // Shared constructor code. 165 void Init(ZeroCopyOutputStream* sub_stream, const Options& options); 166 167 // Do some compression. 168 // Takes zlib flush mode. 169 // Returns zlib error code. 170 int Deflate(int flush); 171 }; 172 173 } // namespace io 174 } // namespace protobuf 175 } // namespace google 176 177 #include "google/protobuf/port_undef.inc" 178 179 #endif // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__ 180