Serenity Operating System
at master 179 lines 5.0 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/IntegralMath.h> 8#include <AK/MemoryStream.h> 9#include <AK/Span.h> 10#include <AK/TypeCasts.h> 11#include <AK/Types.h> 12#include <LibCompress/Deflate.h> 13#include <LibCompress/Zlib.h> 14 15namespace Compress { 16 17constexpr static size_t Adler32Size = sizeof(u32); 18 19Optional<ZlibDecompressor> ZlibDecompressor::try_create(ReadonlyBytes data) 20{ 21 if (data.size() < (sizeof(ZlibHeader) + Adler32Size)) 22 return {}; 23 24 ZlibHeader header { .as_u16 = data.at(0) << 8 | data.at(1) }; 25 26 if (header.compression_method != ZlibCompressionMethod::Deflate || header.compression_info > 7) 27 return {}; // non-deflate compression 28 29 if (header.present_dictionary) 30 return {}; // we dont support pre-defined dictionaries 31 32 if (header.as_u16 % 31 != 0) 33 return {}; // error correction code doesn't match 34 35 ZlibDecompressor zlib { header, data }; 36 zlib.m_data_bytes = data.slice(2, data.size() - sizeof(ZlibHeader) - Adler32Size); 37 return zlib; 38} 39 40ZlibDecompressor::ZlibDecompressor(ZlibHeader header, ReadonlyBytes data) 41 : m_header(header) 42 , m_input_data(data) 43{ 44} 45 46Optional<ByteBuffer> ZlibDecompressor::decompress() 47{ 48 auto buffer_or_error = DeflateDecompressor::decompress_all(m_data_bytes); 49 if (buffer_or_error.is_error()) 50 return {}; 51 return buffer_or_error.release_value(); 52} 53 54Optional<ByteBuffer> ZlibDecompressor::decompress_all(ReadonlyBytes bytes) 55{ 56 auto zlib = try_create(bytes); 57 if (!zlib.has_value()) 58 return {}; 59 return zlib->decompress(); 60} 61 62u32 ZlibDecompressor::checksum() 63{ 64 if (!m_checksum) { 65 auto bytes = m_input_data.slice_from_end(Adler32Size); 66 m_checksum = bytes.at(0) << 24 | bytes.at(1) << 16 | bytes.at(2) << 8 || bytes.at(3); 67 } 68 69 return m_checksum; 70} 71 72ErrorOr<NonnullOwnPtr<ZlibCompressor>> ZlibCompressor::construct(MaybeOwned<Stream> stream, ZlibCompressionLevel compression_level) 73{ 74 // Zlib only defines Deflate as a compression method. 75 auto compression_method = ZlibCompressionMethod::Deflate; 76 77 // FIXME: Find a way to compress with Deflate's "Best" compression level. 78 auto compressor_stream = TRY(DeflateCompressor::construct(MaybeOwned(*stream), static_cast<DeflateCompressor::CompressionLevel>(compression_level))); 79 80 auto zlib_compressor = TRY(adopt_nonnull_own_or_enomem(new (nothrow) ZlibCompressor(move(stream), move(compressor_stream)))); 81 TRY(zlib_compressor->write_header(compression_method, compression_level)); 82 83 return zlib_compressor; 84} 85 86ZlibCompressor::ZlibCompressor(MaybeOwned<Stream> stream, NonnullOwnPtr<Stream> compressor_stream) 87 : m_output_stream(move(stream)) 88 , m_compressor(move(compressor_stream)) 89{ 90} 91 92ZlibCompressor::~ZlibCompressor() 93{ 94 VERIFY(m_finished); 95} 96 97ErrorOr<void> ZlibCompressor::write_header(ZlibCompressionMethod compression_method, ZlibCompressionLevel compression_level) 98{ 99 u8 compression_info = 0; 100 if (compression_method == ZlibCompressionMethod::Deflate) { 101 compression_info = AK::log2(DeflateCompressor::window_size) - 8; 102 VERIFY(compression_info <= 7); 103 } 104 105 ZlibHeader header { 106 .compression_method = compression_method, 107 .compression_info = compression_info, 108 .check_bits = 0, 109 .present_dictionary = false, 110 .compression_level = compression_level, 111 }; 112 header.check_bits = 0b11111 - header.as_u16 % 31; 113 114 // FIXME: Support pre-defined dictionaries. 115 116 TRY(m_output_stream->write_until_depleted(header.as_u16.bytes())); 117 118 return {}; 119} 120 121ErrorOr<Bytes> ZlibCompressor::read_some(Bytes) 122{ 123 return Error::from_errno(EBADF); 124} 125 126ErrorOr<size_t> ZlibCompressor::write_some(ReadonlyBytes bytes) 127{ 128 VERIFY(!m_finished); 129 130 size_t n_written = TRY(m_compressor->write_some(bytes)); 131 m_adler32_checksum.update(bytes.trim(n_written)); 132 return n_written; 133} 134 135bool ZlibCompressor::is_eof() const 136{ 137 return false; 138} 139 140bool ZlibCompressor::is_open() const 141{ 142 return m_output_stream->is_open(); 143} 144 145void ZlibCompressor::close() 146{ 147} 148 149ErrorOr<void> ZlibCompressor::finish() 150{ 151 VERIFY(!m_finished); 152 153 if (is<DeflateCompressor>(m_compressor.ptr())) 154 TRY(static_cast<DeflateCompressor*>(m_compressor.ptr())->final_flush()); 155 156 NetworkOrdered<u32> adler_sum = m_adler32_checksum.digest(); 157 TRY(m_output_stream->write_value(adler_sum)); 158 159 m_finished = true; 160 161 return {}; 162} 163 164ErrorOr<ByteBuffer> ZlibCompressor::compress_all(ReadonlyBytes bytes, ZlibCompressionLevel compression_level) 165{ 166 auto output_stream = TRY(try_make<AllocatingMemoryStream>()); 167 auto zlib_stream = TRY(ZlibCompressor::construct(MaybeOwned<Stream>(*output_stream), compression_level)); 168 169 TRY(zlib_stream->write_until_depleted(bytes)); 170 171 TRY(zlib_stream->finish()); 172 173 auto buffer = TRY(ByteBuffer::create_uninitialized(output_stream->used_buffer_size())); 174 TRY(output_stream->read_until_filled(buffer.bytes())); 175 176 return buffer; 177} 178 179}