FileSystemInfo クラスっぽい FileSystemEntry クラスを書いてみた

メモどまりの[ってみた]だけじゃあれなので、久しぶりに役に立ちそうな感じのを書いてみるよっ。
FileSystemInfo クラス[msdn.microsoft.com]ってのは、 .NET Framework に入ってる、System.IO 名前空間に入ってるクラスだよ。
前に書いたけど、.NET Framework のファイル / ディレクトリ操作 API は パスの文字数に制限があって*1、266 文字のパスを扱えなかった。
なので、自分で FileSystemInfo 相当のクラスを作るしかなかったんだよね。
大体わかったので、今度はそれを C++ で書いてみることにしよう。
VS のデバッグ画面で、FileSystemInfo は、_data という WIN32_FILE_ATTRIBUTE_DATA を中に持ってることが分かった。
WIN32_FILE_ATTRIBUTE_DATA って何かというと…

Contains attribute information for a file or directory. The GetFileAttributesEx function uses this structure.

英語*2だけど、コードとプログラミングに使う単語を覚えていればわかるはず。
この構造体は、GetFileAttributesEx 関数で使います、ってことらしい。
でも、どんなタイミングで取り出してるんだろう? FileSystemInfo クラスにはなんて書いてあるかというと

FileSystemInfo では、最初に呼び出されたときに Refresh を呼び出し、属性の取得などを行う API に関するキャッシュされた情報を返します。 以降の呼び出しでは、Refresh を呼び出して、最新の情報を取得する必要があります。

「最初に呼び出されたときに」何が最初に呼び出された時なのか分からないけれど、私はここの記述にインスピレーションを見いだして、書いてみた。
つまり、コンストラクタで、最初の refresh() を呼びだすってこと。
今思いついた方法では、プロパティがアクセスされたときに最初の refresh() を呼びだすんだけど、そっちで書いてみよう。

class FileSystemEntry
{
 protected:
    FileSystemEntry(const std::string& path)
         : full_path_(), original_path_(path), data_(NULL), data_initialized_(-1)
    {
    }


    virtual ~FileSystemEntry() {
        if ( data_initialized_ == 1 ) {
            delete data_;
            data_ = NULL;
        }
    }

 public:
    void refresh() {
        if ( data_initialized_ == -1 ) {
            data_             = new WIN32_FILE_ATTRIBUTE_DATA();
            data_initialized_ = 1;
        }
        /* (1) */
    }

 protected:
    std::string                 full_path_;

 private:
    std::string                 original_path_;
    WIN32_FILE_ATTRIBUTE_DATA*  data_;
    int                         data_initialized_;
};

ソース中の (1) にはいよいよ GetFileAttributesEx を書いて\(ファイル\|ディレクトリ\)情報を取得するコードを書くわけだけど、
また次回ってことで〜。

*1:260 文字。それより長いパスを渡すと、PathTooLongException がぶっ飛ぶんだ…

*2:なぜか構造体のリファレンスは日本語には無い…