lzh_file_source (圧縮版)

ようやくLZHデコード処理を組み込みました。
対応ヘッダはLevel 0〜2で、圧縮方法はlh4〜lh7をサポートしています。
<hamigaki/iostreams/filter/sliding_window.hpp>
<hamigaki/iostreams/filter/lzhuff.hpp>
lzh_file.hppの差分


性能を測るため、23MBの適当なLZHファイルの展開速度を計測してみました。

ツール 時間
UNLHA32.DLL 5秒
lzh_file_source 33秒

破滅的に遅いですね。
Cygwinでプロファイリングしてみたところ、時間を食っているのはハフマンデコードの処理でした。(スライド辞書は遅くなりようもないので当然です。)
さすがに1ビットごとに二分探索するのは遅かったようで、別のアルゴリズムを模索中です。
ちょっと気になるのは、例外処理アンワインド情報の登録/解除だけで、3〜4秒もかかっていることです。
VC++だと状況は多少違ってくるかもしれませんが、UNLHA32.DLLに勝つのは厳しそうです。


以下、テストに使ったコードです。
ファイルのプロパティにアクセスする方法が変わっていますが、内容は無圧縮版の時とほぼ同じです。

#include <hamigaki/iostreams/device/lzh_file.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/filesystem/operations.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/copy.hpp>
#include <clocale>
#include <exception>
#include <iostream>

namespace io_ex = hamigaki::iostreams;
namespace fs = boost::filesystem;
namespace io = boost::iostreams;

int main(int argc, char* argv[])
{
    try
    {
        if (argc != 2)
            return 1;

        // これがないとfopen()でVC8で日本語ファイル名が化ける
        std::setlocale(LC_ALL, "");

        fs::path::default_name_check(fs::no_check);

        typedef io_ex::lzh_file_source<io::file_source> lzh_type;
        lzh_type lzh(io::file_source(argv[1], std::ios_base::binary));

        do
        {
            const io_ex::lha::basic_header& head = lzh.header();
            if (head.attributes & io_ex::lha::attributes::directory)
                fs::create_directories(head.path);
            else
            {
                fs::create_directories(head.path.branch_path());

                io::copy(
                    lzh,
                    io::file_sink(
                        head.path.native_file_string(), std::ios_base::binary)
                );
            }

        } while (lzh.next_entry());

        return 0;
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
    return 1;
}