今度こそlh6/lh7対応
lh6/7対応といいつつ全然テストしてなかったので、試してみたら案の定動きませんでした。
lh6/7だとスライド辞書のサイズが大きくなっている分、一致位置のビット長のハフマンテーブルが大きくなっているようです。
lzhuff.hppの差分
手元の適当な書庫で試した限り、この修正で問題なさそうです。
その他、ヘッダ周りもろもろ修正しました。
- Level 0/1のファイル更新日時の日付と時間が逆になっていたのを修正
- Level 0/1のヘッダチェックサムに対応
- Windowsタイムスタンプ拡張ヘッダに対応
- UNIX更新時間拡張ヘッダに対応
- UNIXパーミッション拡張ヘッダに対応
Level 1ヘッダのチェックサム処理がちょっとややこしくて、CRC-16と単純な総和の両方を求める必要があるので、
// バイトの総和を求める class lha_checksum { public: lha_checksum() : sum_(0) { } void process_byte(unsigned char byte) { sum_ += byte; } void process_bytes(void const* buffer, std::size_t byte_count) { sum_ += std::accumulate( static_cast<const unsigned char*>(buffer), static_cast<const unsigned char*>(buffer) + byte_count, 0u ); } unsigned char checksum() { return static_cast<unsigned char>(sum_); } private: unsigned sum_; }; // CRC-16とバイトの総和を同時に求める class crc16_and_lha_checksum { public: // CRCは拡張ヘッダまで数えるので参照で渡す explicit crc16_and_lha_checksum(boost::crc_16_type& crc) : crc_(crc) { } void process_byte(unsigned char byte) { crc_.process_byte(byte); cs_.process_byte(byte); } void process_bytes(void const* buffer, std::size_t byte_count) { crc_.process_bytes(buffer, byte_count); cs_.process_bytes(buffer, byte_count); } unsigned char checksum() { return cs_.checksum(); } private: boost::crc_16_type& crc_; lha_checksum cs_; };
のようにBoost.CRCに似せたインタフェースのクラスを作って、処理の共通化を図っています。
(しかも、バイトの総和には先頭2バイトを含めなくて、CRC-16には含めるメンドイ仕様)
サンプルコードもアップしています。
展開(解凍)処理は大体できた感じなので、次は圧縮処理に取り掛かろうと思います。