| 80 | } |
| 81 | |
| 82 | void |
| 83 | GzipDeflateTransformation::consume(std::string_view data) |
| 84 | { |
| 85 | if (data.size() == 0) { |
| 86 | return; |
| 87 | } |
| 88 | |
| 89 | if (!state_->z_stream_initialized_) { |
| 90 | LOG_ERROR("Unable to deflate output because the z_stream was not initialized."); |
| 91 | return; |
| 92 | } |
| 93 | |
| 94 | int iteration = 0; |
| 95 | state_->z_stream_.data_type = Z_ASCII; |
| 96 | state_->z_stream_.next_in = reinterpret_cast<unsigned char *>(const_cast<char *>(data.data())); |
| 97 | state_->z_stream_.avail_in = data.length(); |
| 98 | |
| 99 | // For small payloads the size can actually be greater than the original input |
| 100 | // so we'll use twice the original size to avoid needless repeated calls to deflate. |
| 101 | unsigned long buffer_size = (data.length() < ONE_KB) ? 2 * ONE_KB : data.length(); |
| 102 | vector<unsigned char> buffer(buffer_size); |
| 103 | |
| 104 | do { |
| 105 | LOG_DEBUG("Iteration %d: Deflate will compress %ld bytes", ++iteration, data.size()); |
| 106 | state_->z_stream_.avail_out = buffer_size; |
| 107 | // next_out needs to be set to nullptr before we return since it points to a local buffer |
| 108 | // coverity[WRAPPER_ESCAPE: FALSE] |
| 109 | state_->z_stream_.next_out = &buffer[0]; |
| 110 | |
| 111 | int err = deflate(&state_->z_stream_, Z_SYNC_FLUSH); |
| 112 | if (Z_OK != err) { |
| 113 | LOG_ERROR("Iteration %d: Deflate failed to compress %ld bytes with error code '%d'", iteration, data.size(), err); |
| 114 | state_->z_stream_.next_out = nullptr; |
| 115 | return; |
| 116 | } |
| 117 | |
| 118 | int bytes_to_write = buffer_size - state_->z_stream_.avail_out; |
| 119 | state_->bytes_produced_ += bytes_to_write; |
| 120 | |
| 121 | LOG_DEBUG("Iteration %d: Deflate compressed %ld bytes to %d bytes, producing output...", iteration, data.size(), |
| 122 | bytes_to_write); |
| 123 | produce(std::string_view(reinterpret_cast<char *>(&buffer[0]), static_cast<size_t>(bytes_to_write))); |
| 124 | } while (state_->z_stream_.avail_out == 0); |
| 125 | |
| 126 | state_->z_stream_.next_out = nullptr; |
| 127 | |
| 128 | if (state_->z_stream_.avail_in != 0) { |
| 129 | LOG_ERROR("Inflate finished with data still remaining in the buffer of size '%u'", state_->z_stream_.avail_in); |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | void |
| 134 | GzipDeflateTransformation::handleInputComplete() |