summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibCompress/Lzma.cpp55
-rw-r--r--Userland/Libraries/LibCompress/Lzma.h3
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);