xref: /aosp_15_r20/external/icing/icing/portable/gzip_stream.h (revision 8b6cd535a057e39b3b86660c4aa06c99747c2136)
1 // Copyright (C) 2009 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // This file contains the definition for classes GzipInputStream and
16 // GzipOutputStream. It is forked from protobuf because these classes are only
17 // provided in libprotobuf-full but we would like to link libicing against the
18 // smaller libprotobuf-lite instead.
19 //
20 // GzipInputStream decompresses data from an underlying
21 // ZeroCopyInputStream and provides the decompressed data as a
22 // ZeroCopyInputStream.
23 //
24 // GzipOutputStream is an ZeroCopyOutputStream that compresses data to
25 // an underlying ZeroCopyOutputStream.
26 
27 #ifndef GOOGLE3_ICING_PORTABLE_GZIP_STREAM_H_
28 #define GOOGLE3_ICING_PORTABLE_GZIP_STREAM_H_
29 
30 #include "icing/portable/zlib.h"
31 #include <google/protobuf/io/zero_copy_stream_impl_lite.h>
32 
33 namespace icing {
34 namespace lib {
35 namespace protobuf_ports {
36 
37 // A ZeroCopyInputStream that reads compressed data through zlib
38 class GzipInputStream : public google::protobuf::io::ZeroCopyInputStream {
39  public:
40   // Format key for constructor
41   enum Format {
42     // zlib will autodetect gzip header or deflate stream
43     AUTO = 0,
44 
45     // GZIP streams have some extra header data for file attributes.
46     GZIP = 1,
47 
48     // Simpler zlib stream format.
49     ZLIB = 2,
50   };
51 
52   // buffer_size and format may be -1 for default of 64kB and GZIP format
53   explicit GzipInputStream(google::protobuf::io::ZeroCopyInputStream* sub_stream,
54                            Format format = AUTO, int buffer_size = -1);
55   virtual ~GzipInputStream();
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   google::protobuf::io::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 GzipOutputStream : public google::protobuf::io::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 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(google::protobuf::io::ZeroCopyOutputStream* sub_stream);
116 
117   // Create a GzipOutputStream with the given options.
118   GzipOutputStream(google::protobuf::io::ZeroCopyOutputStream* sub_stream,
119                    const Options& options);
120 
121   virtual ~GzipOutputStream();
122 
123   // Return last error message or NULL if no error.
ZlibErrorMessage()124   inline const char* ZlibErrorMessage() const { return zcontext_.msg; }
ZlibErrorCode()125   inline int ZlibErrorCode() const { return zerror_; }
126 
127   // Flushes data written so far to zipped data in the underlying stream.
128   // It is the caller's responsibility to flush the underlying stream if
129   // necessary.
130   // Compression may be less efficient stopping and starting around flushes.
131   // Returns true if no error.
132   //
133   // Please ensure that block size is > 6. Here is an excerpt from the zlib
134   // doc that explains why:
135   //
136   // In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out
137   // is greater than six to avoid repeated flush markers due to
138   // avail_out == 0 on return.
139   bool Flush();
140 
141   // Writes out all data and closes the gzip stream.
142   // It is the caller's responsibility to close the underlying stream if
143   // necessary.
144   // Returns true if no error.
145   bool Close();
146 
147   // implements ZeroCopyOutputStream ---------------------------------
148   bool Next(void** data, int* size) override;
149   void BackUp(int count) override;
150   int64_t ByteCount() const override;
151 
152  private:
153   google::protobuf::io::ZeroCopyOutputStream* sub_stream_;
154   // Result from calling Next() on sub_stream_
155   void* sub_data_;
156   int sub_data_size_;
157 
158   z_stream zcontext_;
159   int zerror_;
160   void* input_buffer_;
161   size_t input_buffer_length_;
162 
163   // Shared constructor code.
164   void Init(google::protobuf::io::ZeroCopyOutputStream* sub_stream,
165             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 protobuf_ports
174 }  // namespace lib
175 }  // namespace icing
176 
177 #endif  // GOOGLE3_ICING_PORTABLE_GZIP_STREAM_H_
178