今度こそ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には含めるメンドイ仕様)

サンプルコードもアップしています。


展開(解凍)処理は大体できた感じなので、次は圧縮処理に取り掛かろうと思います。