| 62 | } |
| 63 | |
| 64 | int ZlibCompressStream::write(const uint8_t* value, int size) { |
| 65 | gsl_Expects(size >= 0); |
| 66 | if (state_ != ZlibStreamState::INITIALIZED) { |
| 67 | logger_->log_error("writeData called in invalid ZlibCompressStream state, state is %hhu", state_); |
| 68 | return -1; |
| 69 | } |
| 70 | |
| 71 | strm_.next_in = const_cast<uint8_t*>(value); |
| 72 | strm_.avail_in = size; |
| 73 | |
| 74 | /* |
| 75 | * deflate consumes all input data it can (i.e. if it has enough output buffer it never leaves input data unconsumed) |
| 76 | * and fills the output buffer to the brim every time it can. This means that the proper way to use deflate is to |
| 77 | * watch avail_out: once deflate does not have to fill it to the brim, then it has consumed all data we have provided |
| 78 | * to it, and does not need more output buffer for the time being. |
| 79 | * When we have no more input data, we must call deflate with Z_FINISH to make it empty its internal buffers and |
| 80 | * close the compressed stream. |
| 81 | */ |
| 82 | do { |
| 83 | logger_->log_trace("writeData has %u B of input data left", strm_.avail_in); |
| 84 | |
| 85 | strm_.next_out = outputBuffer_.data(); |
| 86 | strm_.avail_out = gsl::narrow<uInt>(outputBuffer_.size()); |
| 87 | |
| 88 | int flush = value == nullptr ? Z_FINISH : Z_NO_FLUSH; |
| 89 | logger_->log_trace("calling deflate with flush %d", flush); |
| 90 | |
| 91 | int ret = deflate(&strm_, flush); |
| 92 | if (ret == Z_STREAM_ERROR) { |
| 93 | logger_->log_error("deflate failed, error code: %d", ret); |
| 94 | state_ = ZlibStreamState::ERRORED; |
| 95 | return -1; |
| 96 | } |
| 97 | int output_size = gsl::narrow<int>(outputBuffer_.size() - strm_.avail_out); |
| 98 | logger_->log_trace("deflate produced %d B of output data", output_size); |
| 99 | if (output_->write(outputBuffer_.data(), output_size) != output_size) { |
| 100 | logger_->log_error("Failed to write to underlying stream"); |
| 101 | state_ = ZlibStreamState::ERRORED; |
| 102 | return -1; |
| 103 | } |
| 104 | } while (strm_.avail_out == 0); |
| 105 | |
| 106 | return size; |
| 107 | } |
| 108 | |
| 109 | void ZlibCompressStream::close() { |
| 110 | if (state_ == ZlibStreamState::INITIALIZED) { |