mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:57:44 +00:00
LibCompress: Implement a Zlib compressor
This commit is contained in:
parent
42abe1df77
commit
0de0de3536
2 changed files with 105 additions and 0 deletions
|
@ -4,7 +4,9 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/MemoryStream.h>
|
||||||
#include <AK/Span.h>
|
#include <AK/Span.h>
|
||||||
|
#include <AK/TypeCasts.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <LibCompress/Deflate.h>
|
#include <LibCompress/Deflate.h>
|
||||||
#include <LibCompress/Zlib.h>
|
#include <LibCompress/Zlib.h>
|
||||||
|
@ -63,4 +65,84 @@ u32 Zlib::checksum()
|
||||||
return m_checksum;
|
return m_checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZlibCompressor::ZlibCompressor(OutputStream& stream, ZlibCompressionLevel compression_level)
|
||||||
|
: m_output_stream(stream)
|
||||||
|
{
|
||||||
|
// Zlib only defines Deflate as a compression method.
|
||||||
|
auto compression_method = ZlibCompressionMethod::Deflate;
|
||||||
|
|
||||||
|
write_header(compression_method, compression_level);
|
||||||
|
|
||||||
|
// FIXME: Find a way to compress with Deflate's "Best" compression level.
|
||||||
|
m_compressor = make<DeflateCompressor>(stream, static_cast<DeflateCompressor::CompressionLevel>(compression_level));
|
||||||
|
}
|
||||||
|
|
||||||
|
ZlibCompressor::~ZlibCompressor()
|
||||||
|
{
|
||||||
|
VERIFY(m_finished);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibCompressor::write_header(ZlibCompressionMethod compression_method, ZlibCompressionLevel compression_level)
|
||||||
|
{
|
||||||
|
ZlibHeader header {
|
||||||
|
.compression_method = compression_method,
|
||||||
|
.compression_info = 0,
|
||||||
|
.check_bits = 0,
|
||||||
|
.present_dictionary = false,
|
||||||
|
.compression_level = compression_level,
|
||||||
|
};
|
||||||
|
header.check_bits = 0b11111 - header.as_u16 % 31;
|
||||||
|
|
||||||
|
// FIXME: Support pre-defined dictionaries.
|
||||||
|
|
||||||
|
m_output_stream << header.as_u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ZlibCompressor::write(ReadonlyBytes bytes)
|
||||||
|
{
|
||||||
|
VERIFY(!m_finished);
|
||||||
|
|
||||||
|
size_t n_written = m_compressor->write(bytes);
|
||||||
|
m_adler32_checksum.update(bytes.trim(n_written));
|
||||||
|
return n_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ZlibCompressor::write_or_error(ReadonlyBytes bytes)
|
||||||
|
{
|
||||||
|
if (write(bytes) < bytes.size()) {
|
||||||
|
set_fatal_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ZlibCompressor::finish()
|
||||||
|
{
|
||||||
|
VERIFY(!m_finished);
|
||||||
|
|
||||||
|
if (is<DeflateCompressor>(m_compressor.ptr()))
|
||||||
|
static_cast<DeflateCompressor*>(m_compressor.ptr())->final_flush();
|
||||||
|
|
||||||
|
NetworkOrdered<u32> adler_sum = m_adler32_checksum.digest();
|
||||||
|
m_output_stream << adler_sum;
|
||||||
|
|
||||||
|
m_finished = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<ByteBuffer> ZlibCompressor::compress_all(ReadonlyBytes bytes, ZlibCompressionLevel compression_level)
|
||||||
|
{
|
||||||
|
DuplexMemoryStream output_stream;
|
||||||
|
ZlibCompressor zlib_stream { output_stream, compression_level };
|
||||||
|
|
||||||
|
zlib_stream.write_or_error(bytes);
|
||||||
|
|
||||||
|
zlib_stream.finish();
|
||||||
|
|
||||||
|
if (zlib_stream.handle_any_error())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return output_stream.copy_into_contiguous_buffer();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/BitStream.h>
|
||||||
#include <AK/ByteBuffer.h>
|
#include <AK/ByteBuffer.h>
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Span.h>
|
#include <AK/Span.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
#include <LibCrypto/Checksum/Adler32.h>
|
||||||
|
|
||||||
namespace Compress {
|
namespace Compress {
|
||||||
|
|
||||||
|
@ -57,4 +60,24 @@ private:
|
||||||
ReadonlyBytes m_data_bytes;
|
ReadonlyBytes m_data_bytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ZlibCompressor : public OutputStream {
|
||||||
|
public:
|
||||||
|
ZlibCompressor(OutputStream&, ZlibCompressionLevel = ZlibCompressionLevel::Default);
|
||||||
|
~ZlibCompressor();
|
||||||
|
|
||||||
|
size_t write(ReadonlyBytes) override;
|
||||||
|
bool write_or_error(ReadonlyBytes) override;
|
||||||
|
void finish();
|
||||||
|
|
||||||
|
static Optional<ByteBuffer> compress_all(ReadonlyBytes bytes, ZlibCompressionLevel = ZlibCompressionLevel::Default);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void write_header(ZlibCompressionMethod, ZlibCompressionLevel);
|
||||||
|
|
||||||
|
bool m_finished { false };
|
||||||
|
OutputBitStream m_output_stream;
|
||||||
|
OwnPtr<OutputStream> m_compressor;
|
||||||
|
Crypto::Checksum::Adler32 m_adler32_checksum;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue