38 #include <google/protobuf/io/gzip_stream.h>
40 #include <google/protobuf/stubs/common.h>
41 #include <google/protobuf/stubs/logging.h>
47 static const int kDefaultBufferSize = 65536;
56 zcontext_.total_out = 0;
57 zcontext_.next_in = NULL;
58 zcontext_.avail_in = 0;
59 zcontext_.total_in = 0;
62 output_buffer_length_ = kDefaultBufferSize;
66 output_buffer_ =
operator new(output_buffer_length_);
68 zcontext_.next_out =
static_cast<Bytef*
>(output_buffer_);
69 zcontext_.avail_out = output_buffer_length_;
70 output_position_ = output_buffer_;
72 GzipInputStream::~GzipInputStream() {
73 operator delete(output_buffer_);
77 static inline int internalInflateInit2(
z_stream* zcontext,
79 int windowBitsFormat = 0;
82 windowBitsFormat = 16;
84 case GzipInputStream::AUTO:
85 windowBitsFormat = 32;
87 case GzipInputStream::ZLIB:
94 int GzipInputStream::Inflate(
int flush) {
95 if ((zerror_ ==
Z_OK) && (zcontext_.avail_out == 0)) {
97 }
else if (zcontext_.avail_in == 0) {
100 bool first = zcontext_.next_in == NULL;
101 bool ok = sub_stream_->Next(&
in, &in_size);
103 zcontext_.next_out = NULL;
104 zcontext_.avail_out = 0;
107 zcontext_.next_in =
static_cast<Bytef*
>(
const_cast<void*
>(
in));
108 zcontext_.avail_in = in_size;
110 int error = internalInflateInit2(&zcontext_, format_);
116 zcontext_.next_out =
static_cast<Bytef*
>(output_buffer_);
117 zcontext_.avail_out = output_buffer_length_;
118 output_position_ = output_buffer_;
123 void GzipInputStream::DoNextOutput(
const void**
data,
int*
size) {
124 *
data = output_position_;
126 output_position_ = zcontext_.next_out;
133 if ((!
ok) || (zcontext_.next_out == NULL)) {
136 if (zcontext_.next_out != output_position_) {
141 if (zcontext_.next_out != NULL) {
145 if (zerror_ !=
Z_OK) {
148 zerror_ = internalInflateInit2(&zcontext_, format_);
149 if (zerror_ !=
Z_OK) {
159 if ((zerror_ ==
Z_STREAM_END) && (zcontext_.next_out == NULL)) {
171 void GzipInputStream::BackUp(
int count) {
172 output_position_ =
reinterpret_cast<void*
>(
188 int64_t GzipInputStream::ByteCount()
const {
190 if (zcontext_.next_out != NULL && output_position_ != NULL) {
191 ret +=
reinterpret_cast<uintptr_t>(zcontext_.next_out) -
192 reinterpret_cast<uintptr_t>(output_position_);
199 GzipOutputStream::Options::Options()
206 Init(sub_stream, Options());
216 sub_stream_ = sub_stream;
220 input_buffer_length_ =
options.buffer_size;
221 input_buffer_ =
operator new(input_buffer_length_);
224 zcontext_.zalloc =
Z_NULL;
226 zcontext_.opaque =
Z_NULL;
227 zcontext_.next_out = NULL;
228 zcontext_.avail_out = 0;
229 zcontext_.total_out = 0;
230 zcontext_.next_in = NULL;
231 zcontext_.avail_in = 0;
232 zcontext_.total_in = 0;
233 zcontext_.msg = NULL;
235 int windowBitsFormat = 16;
237 windowBitsFormat = 0;
241 15 | windowBitsFormat,
242 8,
options.compression_strategy);
245 GzipOutputStream::~GzipOutputStream() {
247 operator delete(input_buffer_);
254 if ((sub_data_ == NULL) || (zcontext_.avail_out == 0)) {
255 bool ok = sub_stream_->Next(&sub_data_, &sub_data_size_);
262 zcontext_.next_out =
static_cast<Bytef*
>(sub_data_);
263 zcontext_.avail_out = sub_data_size_;
266 }
while (
error ==
Z_OK && zcontext_.avail_out == 0);
269 sub_stream_->BackUp(zcontext_.avail_out);
282 if (zcontext_.avail_in != 0) {
284 if (zerror_ !=
Z_OK) {
288 if (zcontext_.avail_in == 0) {
290 zcontext_.next_in =
static_cast<Bytef*
>(input_buffer_);
291 zcontext_.avail_in = input_buffer_length_;
292 *
data = input_buffer_;
293 *
size = input_buffer_length_;
296 GOOGLE_LOG(DFATAL) <<
"Deflate left bytes unconsumed";
300 void GzipOutputStream::BackUp(
int count) {
302 zcontext_.avail_in -=
count;
304 int64_t GzipOutputStream::ByteCount()
const {
305 return zcontext_.total_in + zcontext_.avail_in;
308 bool GzipOutputStream::Flush() {
311 return (zerror_ ==
Z_OK) ||
312 (zerror_ ==
Z_BUF_ERROR && zcontext_.avail_in == 0 &&
313 zcontext_.avail_out != 0);
322 }
while (zerror_ ==
Z_OK);
324 bool ok = zerror_ ==
Z_OK;