• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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