| 136 | } |
| 137 | |
| 138 | inline bool GzipDecompressBase( |
| 139 | const butil::IOBuf& data, butil::IOBuf* msg, |
| 140 | google::protobuf::io::GzipInputStream::Format format) { |
| 141 | butil::IOBufAsZeroCopyInputStream wrapper(data); |
| 142 | google::protobuf::io::GzipInputStream in(&wrapper, format); |
| 143 | butil::IOBufAsZeroCopyOutputStream out(msg); |
| 144 | const void* data_in = NULL; |
| 145 | int size_in = 0; |
| 146 | void* data_out = NULL; |
| 147 | int size_out = 0; |
| 148 | while (1) { |
| 149 | if (size_out == 0 && !out.Next(&data_out, &size_out)) { |
| 150 | break; |
| 151 | } |
| 152 | if (size_in == 0 && !in.Next(&data_in, &size_in)) { |
| 153 | break; |
| 154 | } |
| 155 | const int size_cp = std::min(size_in, size_out); |
| 156 | memcpy(data_out, data_in, size_cp); |
| 157 | size_in -= size_cp; |
| 158 | data_in = (char*)data_in + size_cp; |
| 159 | size_out -= size_cp; |
| 160 | data_out = (char*)data_out + size_cp; |
| 161 | } |
| 162 | if (size_in != 0 || |
| 163 | (size_t)wrapper.ByteCount() != data.size() || |
| 164 | in.Next(&data_in, &size_in)) { |
| 165 | // If any stage is not fully consumed, something went wrong. |
| 166 | // Here we call in.Next addtitionally to make sure that the gzip |
| 167 | // "blackbox" does not have buffer left. |
| 168 | LOG(WARNING) << "Fail to decompress, format=" << Format2CStr(format) |
| 169 | << " : " << in.ZlibErrorMessage(); |
| 170 | return false; |
| 171 | } |
| 172 | if (size_out != 0) { |
| 173 | out.BackUp(size_out); |
| 174 | } |
| 175 | return true; |
| 176 | } |
| 177 | |
| 178 | bool ZlibCompress(const google::protobuf::Message& msg, butil::IOBuf* buf) { |
| 179 | return Compress(msg, buf, google::protobuf::io::GzipOutputStream::ZLIB); |
no test coverage detected