diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index 7155463ebe071..8789bbf23d65e 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -10,6 +10,8 @@ // This file contains the implementation of classes GzipInputStream and // GzipOutputStream. +#include +#define HAVE_ZLIB 1 #if HAVE_ZLIB #include "google/protobuf/io/gzip_stream.h" @@ -37,6 +39,18 @@ GzipInputStream::GzipInputStream(ZeroCopyInputStream* sub_stream, Format format, zcontext_.avail_in = 0; zcontext_.total_in = 0; zcontext_.msg = nullptr; +#else + zcontext_ = new z_stream; + zcontext_->state = Z_NULL; + zcontext_->zalloc = Z_NULL; + zcontext_->zfree = Z_NULL; + zcontext_->opaque = Z_NULL; + zcontext_->total_out = 0; + zcontext_->next_in = nullptr; + zcontext_->avail_in = 0; + zcontext_->total_in = 0; + zcontext_->msg = nullptr; + if (buffer_size == -1) { output_buffer_length_ = kDefaultBufferSize; } else { @@ -46,11 +60,17 @@ GzipInputStream::GzipInputStream(ZeroCopyInputStream* sub_stream, Format format, ABSL_CHECK(output_buffer_ != nullptr); zcontext_.next_out = static_cast(output_buffer_); zcontext_.avail_out = output_buffer_length_; +#else + zcontext_->next_out = static_cast(output_buffer_); + zcontext_->avail_out = output_buffer_length_; output_position_ = output_buffer_; } GzipInputStream::~GzipInputStream() { internal::SizedDelete(output_buffer_, output_buffer_length_); zerror_ = inflateEnd(&zcontext_); +#else + zerror_ = inflateEnd(zcontext_); + delete zcontext_; } static inline int internalInflateInit2(z_stream* zcontext, @@ -97,12 +117,42 @@ int GzipInputStream::Inflate(int flush) { output_position_ = output_buffer_; int error = inflate(&zcontext_, flush); return error; +#else + if ((zerror_ == Z_OK) && (zcontext_->avail_out == 0)) { + // previous inflate filled output buffer. don't change input params yet. + } else if (zcontext_->avail_in == 0) { + const void* in; + int in_size; + bool first = zcontext_->next_in == nullptr; + bool ok = sub_stream_->Next(&in, &in_size); + if (!ok) { + zcontext_->next_out = nullptr; + zcontext_->avail_out = 0; + return Z_STREAM_END; + } + zcontext_->next_in = static_cast(const_cast(in)); + zcontext_->avail_in = in_size; + if (first) { + int error = internalInflateInit2(zcontext_, format_); + if (error != Z_OK) { + return error; + } + } + } + zcontext_->next_out = static_cast(output_buffer_); + zcontext_->avail_out = output_buffer_length_; + output_position_ = output_buffer_; + int error = inflate(zcontext_, flush); + return error; } void GzipInputStream::DoNextOutput(const void** data, int* size) { *data = output_position_; *size = ((uintptr_t)zcontext_.next_out) - ((uintptr_t)output_position_); output_position_ = zcontext_.next_out; +#else + *size = ((uintptr_t)zcontext_->next_out) - ((uintptr_t)output_position_); + output_position_ = zcontext_->next_out; } // implements ZeroCopyInputStream ---------------------------------- @@ -139,6 +189,39 @@ bool GzipInputStream::Next(const void** data, int* size) { // The underlying stream's Next returned false inside Inflate. return false; } +#else + bool ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) || + (zerror_ == Z_BUF_ERROR); + if ((!ok) || (zcontext_->next_out == nullptr)) { + return false; + } + if (zcontext_->next_out != output_position_) { + DoNextOutput(data, size); + return true; + } + if (zerror_ == Z_STREAM_END) { + if (zcontext_->next_out != nullptr) { + // sub_stream_ may have concatenated streams to follow + zerror_ = inflateEnd(zcontext_); + byte_count_ += zcontext_->total_out; + if (zerror_ != Z_OK) { + return false; + } + zerror_ = internalInflateInit2(zcontext_, format_); + if (zerror_ != Z_OK) { + return false; + } + } else { + *data = nullptr; + *size = 0; + return false; + } + } + zerror_ = Inflate(Z_NO_FLUSH); + if ((zerror_ == Z_STREAM_END) && (zcontext_->next_out == nullptr)) { + // The underlying stream's Next returned false inside Inflate. + return false; + } ok = (zerror_ == Z_OK) || (zerror_ == Z_STREAM_END) || (zerror_ == Z_BUF_ERROR); if (!ok) { @@ -171,8 +254,16 @@ int64_t GzipInputStream::ByteCount() const { reinterpret_cast(output_position_); } return ret; +#else + int64_t ret = byte_count_ + zcontext_->total_out; + if (zcontext_->next_out != nullptr && output_position_ != nullptr) { + ret += reinterpret_cast(zcontext_->next_out) - + reinterpret_cast(output_position_); + } + return ret; } + // ========================================================================= GzipOutputStream::Options::Options() @@ -210,6 +301,18 @@ void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream, zcontext_.avail_in = 0; zcontext_.total_in = 0; zcontext_.msg = nullptr; +#else + zcontext_ = new z_stream; + zcontext_->zalloc = Z_NULL; + zcontext_->zfree = Z_NULL; + zcontext_->opaque = Z_NULL; + zcontext_->next_out = nullptr; + zcontext_->avail_out = 0; + zcontext_->total_out = 0; + zcontext_->next_in = nullptr; + zcontext_->avail_in = 0; + zcontext_->total_in = 0; + zcontext_->msg = nullptr; // default to GZIP format int windowBitsFormat = 16; if (options.format == ZLIB) { @@ -219,6 +322,11 @@ void GzipOutputStream::Init(ZeroCopyOutputStream* sub_stream, deflateInit2(&zcontext_, options.compression_level, Z_DEFLATED, /* windowBits */ 15 | windowBitsFormat, /* memLevel (default) */ 8, options.compression_strategy); +#else + zerror_ = + deflateInit2(zcontext_, options.compression_level, Z_DEFLATED, + /* windowBits */ 15 | windowBitsFormat, + /* memLevel (default) */ 8, options.compression_strategy); } GzipOutputStream::~GzipOutputStream() { @@ -252,6 +360,30 @@ int GzipOutputStream::Deflate(int flush) { sub_data_size_ = 0; } return error; +#else + int error = Z_OK; + do { + if ((sub_data_ == nullptr) || (zcontext_->avail_out == 0)) { + bool ok = sub_stream_->Next(&sub_data_, &sub_data_size_); + if (!ok) { + sub_data_ = nullptr; + sub_data_size_ = 0; + return Z_BUF_ERROR; + } + ABSL_CHECK_GT(sub_data_size_, 0); + zcontext_->next_out = static_cast(sub_data_); + zcontext_->avail_out = sub_data_size_; + } + error = deflate(zcontext_, flush); + } while (error == Z_OK && zcontext_->avail_out == 0); + if ((flush == Z_FULL_FLUSH) || (flush == Z_FINISH)) { + // Notify lower layer of data. + sub_stream_->BackUp(zcontext_->avail_out); + // We don't own the buffer anymore. + sub_data_ = nullptr; + sub_data_size_ = 0; + } + return error; } // implements ZeroCopyOutputStream --------------------------------- @@ -276,21 +408,52 @@ bool GzipOutputStream::Next(void** data, int* size) { ABSL_DLOG(FATAL) << "Deflate left bytes unconsumed"; } return true; +#else + if ((zerror_ != Z_OK) && (zerror_ != Z_BUF_ERROR)) { + return false; + } + if (zcontext_->avail_in != 0) { + zerror_ = Deflate(Z_NO_FLUSH); + if (zerror_ != Z_OK) { + return false; + } + } + if (zcontext_->avail_in == 0) { + // all input was consumed. reset the buffer. + zcontext_->next_in = static_cast(input_buffer_); + zcontext_->avail_in = input_buffer_length_; + *data = input_buffer_; + *size = input_buffer_length_; + } else { + // The loop in Deflate should consume all avail_in + ABSL_DLOG(FATAL) << "Deflate left bytes unconsumed"; + } + return true; } void GzipOutputStream::BackUp(int count) { ABSL_CHECK_GE(zcontext_.avail_in, static_cast(count)); zcontext_.avail_in -= count; +#else + ABSL_CHECK_GE(zcontext_->avail_in, static_cast(count)); + zcontext_->avail_in -= count; } int64_t GzipOutputStream::ByteCount() const { return zcontext_.total_in + zcontext_.avail_in; +#else + return zcontext_->total_in + zcontext_->avail_in; } + bool GzipOutputStream::Flush() { zerror_ = Deflate(Z_FULL_FLUSH); // Return true if the flush succeeded or if it was a no-op. + return (zerror_ == Z_OK || + (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 && + zcontext_.avail_out != 0); +#else return (zerror_ == Z_OK) || - (zerror_ == Z_BUF_ERROR && zcontext_.avail_in == 0 && - zcontext_.avail_out != 0); + (zerror_ == Z_BUF_ERROR && zcontext_->avail_in == 0 && + zcontext_->avail_out != 0); } bool GzipOutputStream::Close() { @@ -301,6 +464,8 @@ bool GzipOutputStream::Close() { zerror_ = Deflate(Z_FINISH); } while (zerror_ == Z_OK); zerror_ = deflateEnd(&zcontext_); +#else + zerror_ = deflateEnd(zcontext_); bool ok = zerror_ == Z_OK; zerror_ = Z_STREAM_END; return ok; diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h index b012d8142e5d2..9a192a50144db 100644 --- a/src/google/protobuf/io/gzip_stream.h +++ b/src/google/protobuf/io/gzip_stream.h @@ -24,10 +24,18 @@ #include "google/protobuf/io/zero_copy_stream.h" #include "google/protobuf/port.h" #include +// Externally we always want to include , but internally we only want to +// do that for Android builds, where we get zlib for free as a shared library. +// Otherwise we have to get zlib from //third_party/zlib. For this +// reason during the migration the rust version of zlib, some classes are +// defined in the .cc file. others checks on PROTO2_OPENSOURCE were set in this +// file to implement this forward declarations only for the internal version. +// TODO - b/477521589: Remove this comment after the migration is complete. // Must be included last. #include "google/protobuf/port_def.inc" + namespace google { namespace protobuf { namespace io { @@ -60,6 +68,9 @@ class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED PROTOBUF_EXPORT const { return zcontext_.msg; } +#else + PROTOBUF_FUTURE_ADD_EARLY_NODISCARD const char* ZlibErrorMessage() const; + PROTOBUF_FUTURE_ADD_EARLY_NODISCARD inline int ZlibErrorCode() const { return zerror_; } @@ -76,7 +87,9 @@ class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED PROTOBUF_EXPORT ZeroCopyInputStream* sub_stream_; - z_stream zcontext_; + z_stream_s zcontext_; +#else + struct z_stream_s* zcontext_; int zerror_; void* output_buffer_; @@ -134,6 +147,9 @@ class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED PROTOBUF_EXPORT const { return zcontext_.msg; } +#else + PROTOBUF_FUTURE_ADD_EARLY_NODISCARD const char* ZlibErrorMessage() const; + PROTOBUF_FUTURE_ADD_EARLY_NODISCARD inline int ZlibErrorCode() const { return zerror_; } @@ -170,7 +186,9 @@ class PROTOBUF_FUTURE_ADD_EARLY_WARN_UNUSED PROTOBUF_EXPORT void* sub_data_; int sub_data_size_; - z_stream zcontext_; + z_stream_s zcontext_; +#else + struct z_stream_s* zcontext_; int zerror_; void* input_buffer_; size_t input_buffer_length_;