LibCompress/Lzw: Move shareable code to a base class

This commit is contained in:
Lucas CHOLLET 2024-04-26 10:33:46 -04:00 committed by Andrew Kaster
parent 70a3f1f02b
commit 945e09e46d
Notes: sideshowbarker 2024-07-17 02:39:10 +09:00

View file

@ -17,23 +17,85 @@
namespace Compress {
template<InputBitStream InputStream>
class LzwDecompressor {
private:
namespace Details {
class LzwState {
public:
u16 add_control_code()
{
u16 const control_code = m_code_table.size();
m_code_table.append(Vector<u8> {});
m_original_code_table.append(Vector<u8> {});
if (m_code_table.size() >= m_table_capacity && m_code_size < max_code_size) {
++m_code_size;
++m_original_code_size;
m_table_capacity *= 2;
}
return control_code;
}
void reset()
{
m_code_table.clear();
m_code_table.extend(m_original_code_table);
m_code_size = m_original_code_size;
m_table_capacity = AK::exp2<u32>(m_code_size);
}
protected:
static constexpr int max_code_size = 12;
public:
explicit LzwDecompressor(MaybeOwned<InputStream> lzw_stream, u8 min_code_size, i32 offset_for_size_change = 0)
: m_bit_stream(move(lzw_stream))
, m_code_size(min_code_size)
LzwState(u8 min_code_size, i32 offset_for_size_change)
: m_code_size(min_code_size)
, m_original_code_size(min_code_size)
, m_table_capacity(AK::exp2<u32>(min_code_size))
, m_offset_for_size_change(offset_for_size_change)
{
init_code_table();
}
void init_code_table()
{
m_code_table.ensure_capacity(m_table_capacity);
for (u16 i = 0; i < m_table_capacity; ++i) {
m_code_table.unchecked_append({ (u8)i });
}
m_original_code_table = m_code_table;
}
void extend_code_table(Vector<u8> const& entry)
{
if (entry.size() > 1 && m_code_table.size() < 4096) {
m_code_table.append(entry);
if (m_code_table.size() >= (m_table_capacity + m_offset_for_size_change) && m_code_size < max_code_size) {
++m_code_size;
m_table_capacity *= 2;
}
}
}
Vector<Vector<u8>> m_code_table {};
Vector<Vector<u8>> m_original_code_table {};
u8 m_code_size { 0 };
u8 m_original_code_size { 0 };
u32 m_table_capacity { 0 };
i32 m_offset_for_size_change {};
};
}
template<InputBitStream InputStream>
class LzwDecompressor : private Details::LzwState {
public:
explicit LzwDecompressor(MaybeOwned<InputStream> lzw_stream, u8 min_code_size, i32 offset_for_size_change = 0)
: LzwState(min_code_size, offset_for_size_change)
, m_bit_stream(move(lzw_stream))
{
}
static ErrorOr<ByteBuffer> decompress_all(ReadonlyBytes bytes, u8 initial_code_size, i32 offset_for_size_change = 0)
{
auto memory_stream = make<FixedMemoryStream>(bytes);
@ -62,25 +124,9 @@ public:
return decompressed;
}
u16 add_control_code()
{
u16 const control_code = m_code_table.size();
m_code_table.append(Vector<u8> {});
m_original_code_table.append(Vector<u8> {});
if (m_code_table.size() >= m_table_capacity && m_code_size < max_code_size) {
++m_code_size;
++m_original_code_size;
m_table_capacity *= 2;
}
return control_code;
}
void reset()
{
m_code_table.clear();
m_code_table.extend(m_original_code_table);
m_code_size = m_original_code_size;
m_table_capacity = AK::exp2<u32>(m_code_size);
LzwState::reset();
m_output.clear();
}
@ -120,37 +166,8 @@ public:
}
private:
void init_code_table()
{
m_code_table.ensure_capacity(m_table_capacity);
for (u16 i = 0; i < m_table_capacity; ++i) {
m_code_table.unchecked_append({ (u8)i });
}
m_original_code_table = m_code_table;
}
void extend_code_table(Vector<u8> const& entry)
{
if (entry.size() > 1 && m_code_table.size() < 4096) {
m_code_table.append(entry);
if (m_code_table.size() >= (m_table_capacity + m_offset_for_size_change) && m_code_size < max_code_size) {
++m_code_size;
m_table_capacity *= 2;
}
}
}
MaybeOwned<InputStream> m_bit_stream;
Vector<Vector<u8>> m_code_table {};
Vector<Vector<u8>> m_original_code_table {};
u8 m_code_size { 0 };
u8 m_original_code_size { 0 };
u32 m_table_capacity { 0 };
i32 m_offset_for_size_change {};
u16 m_current_code { 0 };
Vector<u8> m_output {};
};