| 37 | } |
| 38 | |
| 39 | bool zlibCompress(IStream& source, uint64_t sourceLength, IStream& dest, ZlibHeaderType header, int16_t level) |
| 40 | { |
| 41 | if (sourceLength > source.GetLength() - source.GetPosition()) |
| 42 | throw IOException("Not Enough Data to Compress"); |
| 43 | |
| 44 | StreamReadBuffer sourceBuf(source, sourceLength, kZlibChunkSize); |
| 45 | StreamWriteBuffer destBuf(dest, zlibCompressBound(sourceLength), kZlibChunkSize); |
| 46 | |
| 47 | z_stream strm{}; |
| 48 | int ret = deflateInit2(&strm, level, Z_DEFLATED, kZlibWindowBits[static_cast<int>(header)], 8, Z_DEFAULT_STRATEGY); |
| 49 | if (ret != Z_OK) |
| 50 | { |
| 51 | LOG_ERROR("Failed to initialise stream"); |
| 52 | return false; |
| 53 | } |
| 54 | |
| 55 | do |
| 56 | { |
| 57 | auto readBlock = sourceBuf.ReadBlock(source, kZlibMaxChunkSize); |
| 58 | strm.next_in = static_cast<const Bytef*>(readBlock.first); |
| 59 | strm.avail_in = static_cast<uInt>(readBlock.second); |
| 60 | |
| 61 | do |
| 62 | { |
| 63 | Guard::Assert(destBuf, "Compression Overruns Ouput Size"); |
| 64 | |
| 65 | auto writeBlock = destBuf.WriteBlockStart(kZlibMaxChunkSize); |
| 66 | strm.next_out = static_cast<Bytef*>(writeBlock.first); |
| 67 | strm.avail_out = static_cast<uInt>(writeBlock.second); |
| 68 | |
| 69 | ret = deflate(&strm, sourceBuf ? Z_NO_FLUSH : Z_FINISH); |
| 70 | if (ret == Z_STREAM_ERROR) |
| 71 | { |
| 72 | LOG_ERROR("Failed to compress data"); |
| 73 | deflateEnd(&strm); |
| 74 | return false; |
| 75 | } |
| 76 | |
| 77 | destBuf.WriteBlockCommit(dest, writeBlock.second - strm.avail_out); |
| 78 | } while (strm.avail_in > 0); |
| 79 | } while (sourceBuf); |
| 80 | |
| 81 | deflateEnd(&strm); |
| 82 | return true; |
| 83 | } |
| 84 | |
| 85 | bool zlibDecompress(IStream& source, uint64_t sourceLength, IStream& dest, uint64_t decompressLength, ZlibHeaderType header) |
| 86 | { |
no test coverage detected