diff options
author | Tim Schumacher <timschumi@gmx.de> | 2023-03-14 04:12:20 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-03-21 10:25:13 +0100 |
commit | f4506a3a72831f009d7244dd8213b21c9eb08ddf (patch) | |
tree | 4661a02236acfd6333612d0c4add129a176a6814 /Userland | |
parent | 04f69de7f1c12c7ac8de46ba7a77c70bd7dcc178 (diff) | |
download | serenity-f4506a3a72831f009d7244dd8213b21c9eb08ddf.zip |
LibCompress: Allow appending input streams to an existing LZMA decoder
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibCompress/Lzma.cpp | 55 | ||||
-rw-r--r-- | Userland/Libraries/LibCompress/Lzma.h | 3 |
2 files changed, 43 insertions, 15 deletions
diff --git a/Userland/Libraries/LibCompress/Lzma.cpp b/Userland/Libraries/LibCompress/Lzma.cpp index e933dbe286..ddf0eb8588 100644 --- a/Userland/Libraries/LibCompress/Lzma.cpp +++ b/Userland/Libraries/LibCompress/Lzma.cpp @@ -99,16 +99,6 @@ ErrorOr<NonnullOwnPtr<LzmaDecompressor>> LzmaDecompressor::create_from_container ErrorOr<NonnullOwnPtr<LzmaDecompressor>> LzmaDecompressor::create_from_raw_stream(MaybeOwned<Stream> stream, LzmaDecompressorOptions const& options) { - // "The LZMA Encoder always writes ZERO in initial byte of compressed stream. - // That scheme allows to simplify the code of the Range Encoder in the - // LZMA Encoder. If initial byte is not equal to ZERO, the LZMA Decoder must - // stop decoding and report error." - { - auto byte = TRY(stream->read_value<u8>()); - if (byte != 0) - return Error::from_string_literal("Initial byte of data stream is not zero"); - } - auto output_buffer = TRY(CircularBuffer::create_empty(options.dictionary_size)); // "The LZMA Decoder uses (1 << (lc + lp)) tables with CProb values, where each table contains 0x300 CProb values." @@ -116,11 +106,7 @@ ErrorOr<NonnullOwnPtr<LzmaDecompressor>> LzmaDecompressor::create_from_raw_strea auto decompressor = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LzmaDecompressor(move(stream), options, move(output_buffer), move(literal_probabilities)))); - // Read the initial bytes into the range decoder. - for (size_t i = 0; i < 4; i++) { - auto byte = TRY(decompressor->m_stream->read_value<u8>()); - decompressor->m_range_decoder_code = decompressor->m_range_decoder_code << 8 | byte; - } + TRY(decompressor->initialize_range_decoder()); return decompressor; } @@ -149,6 +135,45 @@ LzmaDecompressor::LzmaDecompressor(MaybeOwned<Stream> stream, LzmaDecompressorOp initialize_to_default_probability(m_is_rep0_long_probabilities); } +ErrorOr<void> LzmaDecompressor::initialize_range_decoder() +{ + // "The LZMA Encoder always writes ZERO in initial byte of compressed stream. + // That scheme allows to simplify the code of the Range Encoder in the + // LZMA Encoder. If initial byte is not equal to ZERO, the LZMA Decoder must + // stop decoding and report error." + { + auto byte = TRY(m_stream->read_value<u8>()); + if (byte != 0) + return Error::from_string_literal("Initial byte of data stream is not zero"); + } + + // Read the initial bytes into the range decoder. + m_range_decoder_code = 0; + for (size_t i = 0; i < 4; i++) { + auto byte = TRY(m_stream->read_value<u8>()); + m_range_decoder_code = m_range_decoder_code << 8 | byte; + } + + m_range_decoder_range = 0xFFFFFFFF; + + return {}; +} + +ErrorOr<void> LzmaDecompressor::append_input_stream(MaybeOwned<Stream> stream, Optional<u64> uncompressed_size) +{ + m_stream = move(stream); + + TRY(initialize_range_decoder()); + + if (m_options.uncompressed_size.has_value() != uncompressed_size.has_value()) + return Error::from_string_literal("Appending LZMA streams with mismatching uncompressed size status"); + + if (uncompressed_size.has_value()) + *m_options.uncompressed_size += *uncompressed_size; + + return {}; +} + ErrorOr<void> LzmaDecompressor::normalize_range_decoder() { // "The value of the "Range" variable before each bit decoding can not be smaller diff --git a/Userland/Libraries/LibCompress/Lzma.h b/Userland/Libraries/LibCompress/Lzma.h index 347e07b705..96f0557bd0 100644 --- a/Userland/Libraries/LibCompress/Lzma.h +++ b/Userland/Libraries/LibCompress/Lzma.h @@ -55,6 +55,8 @@ public: /// Creates a decompressor from a raw stream of LZMA-compressed data (found inside an LZMA container or embedded in other file formats). static ErrorOr<NonnullOwnPtr<LzmaDecompressor>> create_from_raw_stream(MaybeOwned<Stream>, LzmaDecompressorOptions const&); + ErrorOr<void> append_input_stream(MaybeOwned<Stream>, Optional<u64> uncompressed_size); + virtual ErrorOr<Bytes> read_some(Bytes) override; virtual ErrorOr<size_t> write_some(ReadonlyBytes) override; virtual bool is_eof() const override; @@ -84,6 +86,7 @@ private: u32 m_range_decoder_range { 0xFFFFFFFF }; u32 m_range_decoder_code { 0 }; + ErrorOr<void> initialize_range_decoder(); ErrorOr<void> normalize_range_decoder(); ErrorOr<u8> decode_direct_bit(); ErrorOr<u8> decode_bit_with_probability(Probability& probability); |