lzokay/lzokay.hpp

76 lines
2.5 KiB
C++
Raw Normal View History

2018-12-23 17:43:24 -08:00
#pragma once
#include <cstddef>
#include <cstdint>
#include <memory>
2022-05-14 15:30:26 -07:00
#include <array>
2018-12-23 17:43:24 -08:00
namespace lzokay {
enum class EResult {
LookbehindOverrun = -4,
OutputOverrun = -3,
InputOverrun = -2,
Error = -1,
Success = 0,
InputNotConsumed = 1,
};
class DictBase {
protected:
static constexpr uint32_t HashSize = 0x4000;
static constexpr uint32_t MaxDist = 0xbfff;
static constexpr uint32_t MaxMatchLen = 0x800;
static constexpr uint32_t BufSize = MaxDist + MaxMatchLen;
/* List encoding of previous 3-byte data matches */
struct Match3 {
2022-05-14 15:30:26 -07:00
std::array<uint16_t, HashSize> head; /* key -> chain-head-pos */
std::array<uint16_t, HashSize> chain_sz; /* key -> chain-size */
std::array<uint16_t, BufSize> chain; /* chain-pos -> next-chain-pos */
std::array<uint16_t, BufSize> best_len; /* chain-pos -> best-match-length */
2018-12-23 17:43:24 -08:00
};
/* Encoding of 2-byte data matches */
struct Match2 {
2022-05-14 15:30:26 -07:00
std::array<uint16_t, 1 << 16> head; /* 2-byte-data -> head-pos */
2018-12-23 17:43:24 -08:00
};
struct Data {
Match3 match3;
Match2 match2;
/* Circular buffer caching enough data to access the maximum lookback
* distance of 48K + maximum match length of 2K. An additional 2K is
* allocated so the start of the buffer may be replicated at the end,
* therefore providing efficient circular access.
*/
2022-05-14 15:30:26 -07:00
std::array<uint8_t, BufSize + MaxMatchLen> buffer;
2018-12-23 17:43:24 -08:00
};
using storage_type = Data;
storage_type* _storage;
DictBase() = default;
friend struct State;
2022-05-14 15:30:26 -07:00
friend EResult compress(const uint8_t* src, std::size_t src_size, uint8_t* dst, std::size_t& dst_size,
DictBase& dict);
2018-12-23 17:43:24 -08:00
};
2022-05-14 15:30:26 -07:00
template <template <typename> class _Alloc = std::allocator>
2018-12-23 17:43:24 -08:00
class Dict : public DictBase {
_Alloc<DictBase::storage_type> _allocator;
2022-05-14 15:30:26 -07:00
2018-12-23 17:43:24 -08:00
public:
Dict() { _storage = _allocator.allocate(1); }
~Dict() { _allocator.deallocate(_storage, 1); }
};
2022-05-14 15:30:26 -07:00
EResult decompress(const uint8_t* src, std::size_t src_size, uint8_t* dst, std::size_t dst_size, std::size_t& out_size);
EResult compress(const uint8_t* src, std::size_t src_size, uint8_t* dst, std::size_t dst_size, std::size_t& out_size,
DictBase& dict);
inline EResult compress(const uint8_t* src, std::size_t src_size, uint8_t* dst, std::size_t dst_size,
std::size_t& out_size) {
2018-12-23 17:43:24 -08:00
Dict<> dict;
return compress(src, src_size, dst, dst_size, out_size, dict);
2018-12-23 17:43:24 -08:00
}
2022-05-14 15:30:26 -07:00
constexpr std::size_t compress_worst_size(std::size_t s) { return s + s / 16 + 64 + 3; }
2018-12-23 17:43:24 -08:00
2022-05-14 15:30:26 -07:00
} // namespace lzokay