| 62 | { |
| 63 | |
| 64 | Expected<void> zlibCompressStream( std::istream& in, std::ostream& out, const ZlibCompressParams& params ) |
| 65 | { |
| 66 | Buffer<char> inChunk( cChunkSize ), outChunk( cChunkSize ); |
| 67 | zng_stream stream { |
| 68 | .zalloc = Z_NULL, |
| 69 | .zfree = Z_NULL, |
| 70 | .opaque = Z_NULL, |
| 71 | }; |
| 72 | int ret; |
| 73 | if ( Z_OK != ( ret = zng_deflateInit2( &stream, params.level, Z_DEFLATED, windowBitsFor( params.rawDeflate ), kDefaultMemLevel, Z_DEFAULT_STRATEGY ) ) ) |
| 74 | return unexpected( zngToString( ret ) ); |
| 75 | |
| 76 | MR_FINALLY { |
| 77 | zng_deflateEnd( &stream ); |
| 78 | }; |
| 79 | |
| 80 | if ( params.stats ) |
| 81 | *params.stats = {}; |
| 82 | |
| 83 | while ( !in.eof() ) |
| 84 | { |
| 85 | in.read( inChunk.data(), inChunk.size() ); |
| 86 | if ( in.bad() ) |
| 87 | return unexpected( "I/O error" ); |
| 88 | stream.next_in = reinterpret_cast<uint8_t*>( inChunk.data() ); |
| 89 | stream.avail_in = (unsigned)in.gcount(); |
| 90 | assert( stream.avail_in <= (unsigned)inChunk.size() ); |
| 91 | |
| 92 | if ( params.stats ) |
| 93 | { |
| 94 | params.stats->crc32 = (uint32_t)zng_crc32( params.stats->crc32, stream.next_in, stream.avail_in ); |
| 95 | params.stats->uncompressedSize += stream.avail_in; |
| 96 | } |
| 97 | |
| 98 | const auto flush = in.eof() ? Z_FINISH : Z_NO_FLUSH; |
| 99 | do |
| 100 | { |
| 101 | stream.next_out = reinterpret_cast<uint8_t*>( outChunk.data() ); |
| 102 | stream.avail_out = (unsigned)outChunk.size(); |
| 103 | ret = zng_deflate( &stream, flush ); |
| 104 | if ( Z_OK != ret && Z_STREAM_END != ret ) |
| 105 | return unexpected( zngToString( ret ) ); |
| 106 | |
| 107 | assert( stream.avail_out <= (unsigned)outChunk.size() ); |
| 108 | const unsigned written = (unsigned)outChunk.size() - stream.avail_out; |
| 109 | out.write( outChunk.data(), written ); |
| 110 | if ( out.bad() ) |
| 111 | return unexpected( "I/O error" ); |
| 112 | if ( params.stats ) |
| 113 | params.stats->compressedSize += written; |
| 114 | } |
| 115 | while ( stream.avail_out == 0 ); |
| 116 | } |
| 117 | |
| 118 | return {}; |
| 119 | } |
| 120 | |
| 121 | Expected<void> zlibCompressStream( std::istream& in, std::ostream& out, int level ) |