mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 21:07:34 +00:00
LibCompress: Add support for XZ
This commit is contained in:
parent
aae1404016
commit
9e990f7329
3 changed files with 611 additions and 0 deletions
136
Userland/Libraries/LibCompress/Xz.h
Normal file
136
Userland/Libraries/LibCompress/Xz.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Tim Schumacher <timschumi@gmx.de>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ConstrainedStream.h>
|
||||
#include <AK/CountingStream.h>
|
||||
#include <AK/Endian.h>
|
||||
#include <AK/Error.h>
|
||||
#include <AK/MaybeOwned.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/Stream.h>
|
||||
|
||||
namespace Compress {
|
||||
|
||||
// This implementation is based on the "The .xz File Format" specification version 1.1.0:
|
||||
// https://tukaani.org/xz/xz-file-format-1.1.0.txt
|
||||
|
||||
// 1.2. Multibyte Integers
|
||||
class [[gnu::packed]] XzMultibyteInteger {
|
||||
public:
|
||||
constexpr XzMultibyteInteger() = default;
|
||||
|
||||
constexpr XzMultibyteInteger(u64 value)
|
||||
: m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr operator u64() const { return m_value; }
|
||||
|
||||
static ErrorOr<XzMultibyteInteger> read_from_stream(Stream& stream);
|
||||
|
||||
private:
|
||||
u64 m_value { 0 };
|
||||
};
|
||||
|
||||
// 2.1.1.2. Stream Flags
|
||||
enum XzStreamCheckType : u8 {
|
||||
None = 0x00,
|
||||
CRC32 = 0x01,
|
||||
CRC64 = 0x04,
|
||||
SHA256 = 0x0A,
|
||||
};
|
||||
|
||||
// 2.1.1.2. Stream Flags
|
||||
struct [[gnu::packed]] XzStreamFlags {
|
||||
u8 reserved;
|
||||
XzStreamCheckType check_type : 4;
|
||||
u8 reserved_bits : 4;
|
||||
};
|
||||
static_assert(sizeof(XzStreamFlags) == 2);
|
||||
|
||||
// 2.1.1. Stream Header
|
||||
struct [[gnu::packed]] XzStreamHeader {
|
||||
u8 magic[6];
|
||||
XzStreamFlags flags;
|
||||
LittleEndian<u32> flags_crc32;
|
||||
|
||||
ErrorOr<void> validate();
|
||||
};
|
||||
static_assert(sizeof(XzStreamHeader) == 12);
|
||||
|
||||
// 2.1.2. Stream Footer
|
||||
struct [[gnu::packed]] XzStreamFooter {
|
||||
LittleEndian<u32> size_and_flags_crc32;
|
||||
LittleEndian<u32> encoded_backward_size;
|
||||
XzStreamFlags flags;
|
||||
u8 magic[2];
|
||||
|
||||
ErrorOr<void> validate();
|
||||
u32 backward_size();
|
||||
};
|
||||
static_assert(sizeof(XzStreamFooter) == 12);
|
||||
|
||||
// 3.1.2. Block Flags
|
||||
struct [[gnu::packed]] XzBlockFlags {
|
||||
u8 encoded_number_of_filters : 2;
|
||||
u8 reserved : 4;
|
||||
bool compressed_size_present : 1;
|
||||
bool uncompressed_size_present : 1;
|
||||
|
||||
u8 number_of_filters();
|
||||
};
|
||||
static_assert(sizeof(XzBlockFlags) == 1);
|
||||
|
||||
// 5.3.1. LZMA2
|
||||
struct [[gnu::packed]] XzFilterLzma2Properties {
|
||||
u8 encoded_dictionary_size : 6;
|
||||
u8 reserved : 2;
|
||||
|
||||
ErrorOr<void> validate();
|
||||
u32 dictionary_size();
|
||||
};
|
||||
static_assert(sizeof(XzFilterLzma2Properties) == 1);
|
||||
|
||||
class XzDecompressor : public Stream {
|
||||
public:
|
||||
static ErrorOr<NonnullOwnPtr<XzDecompressor>> create(MaybeOwned<Stream>);
|
||||
|
||||
virtual ErrorOr<Bytes> read_some(Bytes) override;
|
||||
virtual ErrorOr<size_t> write_some(ReadonlyBytes) override;
|
||||
virtual bool is_eof() const override;
|
||||
virtual bool is_open() const override;
|
||||
virtual void close() override;
|
||||
|
||||
private:
|
||||
XzDecompressor(NonnullOwnPtr<CountingStream>, XzStreamFlags);
|
||||
|
||||
NonnullOwnPtr<CountingStream> m_stream;
|
||||
XzStreamFlags m_stream_flags;
|
||||
bool m_found_stream_footer { false };
|
||||
|
||||
Optional<MaybeOwned<Stream>> m_current_block_stream {};
|
||||
Optional<u64> m_current_block_uncompressed_size {};
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct AK::Traits<Compress::XzStreamHeader> : public AK::GenericTraits<Compress::XzStreamHeader> {
|
||||
static constexpr bool is_trivially_serializable() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AK::Traits<Compress::XzStreamFooter> : public AK::GenericTraits<Compress::XzStreamFooter> {
|
||||
static constexpr bool is_trivially_serializable() { return true; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AK::Traits<Compress::XzBlockFlags> : public AK::GenericTraits<Compress::XzBlockFlags> {
|
||||
static constexpr bool is_trivially_serializable() { return true; }
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue