void TZlibTransport::flushToZlib(const uint8_t* buf, int len, int flush) { wstream_->next_in = const_cast<uint8_t*>(buf); wstream_->avail_in = len; while (true) { if (flush == Z_NO_FLUSH && wstream_->avail_in == 0) { break; } // If our ouput buffer is full, flush to the underlying transport. if (wstream_->avail_out == 0) { transport_->write(cwbuf_, cwbuf_size_); wstream_->next_out = cwbuf_; wstream_->avail_out = cwbuf_size_; } int zlib_rv = deflate(wstream_, flush); if (flush == Z_FINISH && zlib_rv == Z_STREAM_END) { assert(wstream_->avail_in == 0); output_finished_ = true; break; } checkZlibRv(zlib_rv, wstream_->msg); if ((flush == Z_SYNC_FLUSH || flush == Z_FULL_FLUSH) && wstream_->avail_in == 0 && wstream_->avail_out != 0) { break; } } }
bool TZlibTransport::readFromZlib() { assert(!input_ended_); // If we don't have any more compressed data available, // read some from the underlying transport. if (rstream_->avail_in == 0) { uint32_t got = transport_->read(crbuf_, crbuf_size_); if (got == 0) { return false; } rstream_->next_in = crbuf_; rstream_->avail_in = got; } // We have some compressed data now. Uncompress it. int zlib_rv = inflate(rstream_, Z_SYNC_FLUSH); if (zlib_rv == Z_STREAM_END) { input_ended_ = true; } else { checkZlibRv(zlib_rv, rstream_->msg); } return true; }
uint32_t TZlibTransport::read(uint8_t* buf, uint32_t len) { int need = len; // TODO(dreiss): Skip urbuf on big reads. while (true) { // Copy out whatever we have available, then give them the min of // what we have and what they want, then advance indices. int give = std::min(readAvail(), need); memcpy(buf, urbuf_ + urpos_, give); need -= give; buf += give; urpos_ += give; // If they were satisfied, we are done. if (need == 0) { return len; } // If we get to this point, we need to get some more data. // If zlib has reported the end of a stream, we can't really do any more. if (input_ended_) { return len - need; } // The uncompressed read buffer is empty, so reset the stream fields. rstream_->next_out = urbuf_; rstream_->avail_out = urbuf_size_; urpos_ = 0; // If we don't have any more compressed data available, // read some from the underlying transport. if (rstream_->avail_in == 0) { uint32_t got = transport_->read(crbuf_, crbuf_size_); if (got == 0) { return len - need; } rstream_->next_in = crbuf_; rstream_->avail_in = got; } // We have some compressed data now. Uncompress it. int zlib_rv = inflate(rstream_, Z_SYNC_FLUSH); if (zlib_rv == Z_STREAM_END) { if (standalone_) { input_ended_ = true; } } else { checkZlibRv(zlib_rv, rstream_->msg); } // Okay. The read buffer should have whatever we can give it now. // Loop back to the start and try to give some more. } }
// Don't call this outside of the constructor. void TZlibTransport::initZlib() { int rv; bool r_init = false; try { rstream_ = new z_stream; wstream_ = new z_stream; rstream_->zalloc = Z_NULL; wstream_->zalloc = Z_NULL; rstream_->zfree = Z_NULL; wstream_->zfree = Z_NULL; rstream_->opaque = Z_NULL; wstream_->opaque = Z_NULL; rstream_->next_in = crbuf_; wstream_->next_in = uwbuf_; rstream_->next_out = urbuf_; wstream_->next_out = cwbuf_; rstream_->avail_in = 0; wstream_->avail_in = 0; rstream_->avail_out = urbuf_size_; wstream_->avail_out = cwbuf_size_; rv = inflateInit(rstream_); checkZlibRv(rv, rstream_->msg); // Have to set this flag so we know whether to de-initialize. r_init = true; rv = deflateInit(wstream_, Z_DEFAULT_COMPRESSION); checkZlibRv(rv, wstream_->msg); } catch (...) { if (r_init) { rv = inflateEnd(rstream_); checkZlibRvNothrow(rv, rstream_->msg); } // There is no way we can get here if wstream_ was initialized. throw; } }
void TZlibTransport::flushToZlib(const uint8_t* buf, int len, bool finish) { int flush = (finish ? Z_FINISH : Z_NO_FLUSH); wstream_->next_in = const_cast<uint8_t*>(buf); wstream_->avail_in = len; while (wstream_->avail_in > 0 || finish) { // If our ouput buffer is full, flush to the underlying transport. if (wstream_->avail_out == 0) { transport_->write(cwbuf_, cwbuf_size_); wstream_->next_out = cwbuf_; wstream_->avail_out = cwbuf_size_; } int zlib_rv = deflate(wstream_, flush); if (finish && zlib_rv == Z_STREAM_END) { assert(wstream_->avail_in == 0); break; } checkZlibRv(zlib_rv, wstream_->msg); } }