ssgnc 改修の進捗

大規模トライのテストにとても時間がかかるので,裏で ssgnc(Google Code Archive - Long-term storage for Google Code Project Hosting.)の修正をしていました.

修正の理由は,「mmap() で確保した領域からの読み込みに std::istream を使うのは無駄が多いから※」とか「インタフェースが使いにくいから」とか「Boost & dawgdic への依存を解消したいから」とか「索引構築の効率が悪いから」などです.一言にまとめると,「気に入らないから」かもしれません.おまけとして,引き継ぎ用という理由も追加できます.

※ 自前のバッファを通しているため,速度に対する影響は小さいはずなのですが,「mmap() -> std::streambuf' -> std::istream -> 自前のバッファ」という流れ自体がどうにも微妙な感じです.

現行バージョン(ssgnc-0.2.2)では,std::streambuf を継承させた以下のようなクラスを使うことで,mmap() により確保した領域でも std::fstream と同様に扱えるようにしています.いわゆる手抜きです.

class MemStreambuf : public std::streambuf
{
public:
  MemStreambuf(const char *buf, std::size_t size)
  {
    char *ptr = const_cast<char *>(buf);
    setg(ptr, ptr, ptr + size);
  }
};

mmap() で確保した領域の一部を MemStreambuf に渡して,その MemStreambuf を std::istream に渡して,その std::istream を ssgnc::ByteReader に渡して,その ssgnc::ByteReader を ssgnc::VarintReader に渡すという構成になっていたと思います….

注記:上記のクラス MemStreambuf を使う場合,2GB 以上のデータをまとめて読み書きしようとすると大変なことになります.理由は,内部で呼び出されるメンバ関数 gbump() や pbump() の引数が int になっていて,オーバーフローしてしまうからです(おそらく環境依存です).この問題は,xsgetn() と xsputn() をオーバーライドすることで解決できます.私は,大規模トライ用ライブラリの開発中に一度ハマりました.