ゲーム用のファイルシステム Part 1
順番にファイルを出していこうと思います。まぁ、まだ完成してはいない部分もあるですが、この辺は変わらないだろうと。
今回は、ファイルインターフェースを定義しているヘッダファイルです。
こういう仕様のものを作りますよ〜という感じで。
ちなみに、細かい部分は以下の方針で実装します。
Unicodeのみに対応します。
どこで変換するかの違いだけですので、このライブラリの外側でShift-JISとかへの変換をお願いしますということで。
2GBを超えるファイルには対応しません。
内部でファイルマッピングオブジェクトを使っている以上、32bit環境下ではどうせ2GBを超えるファイルは上手く動かないよね、ということで。
私はどうせそんな大きなファイルは使わないですし。
Doxygenでドキュメント生成ができるようにコメントを書きます。
後でマニュアルとして使えるように。
全部ライブラリ専用の名前空間に入れます。
だってIFileとかCFileとか簡単に名前が衝突するでしょ、ということで。
ah_file.hpp
// **************************************************************** /*! @file @brief AHLIBファイルインターフェース定義 @author 藍川翡翠 @date 2010/09/05 */ #pragma once #include <objidl.h> // ---------------------------------------------------------------- //! AHLIB namespace ah { // **************************************************************** /*! @brief ファイルインターフェース */ class IFile : public IStream { public: /*! @brief インターフェース問い合わせ @param[in] iid インターフェースID @param[out] ppvObject インターフェースの格納先 @return HRESULT */ virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject) = 0; /*! @brief 参照カウンタインクリメント @return 新しい参照カウンタ値 */ virtual ULONG STDMETHODCALLTYPE AddRef(void) = 0; /*! @brief 参照カウンタデクリメント @return 新しい参照カウンタ値 */ virtual ULONG STDMETHODCALLTYPE Release(void) = 0; /*! @brief ファイルから読み込み @param[out] pv データの格納場所 @param[in] lSize 項目のサイズ @param[in] lCount 読み出す最大項目数 @return 読み取った項目の数 */ virtual long STDMETHODCALLTYPE Read(void* pv, long lSize, long lCount) = 0; /*! @brief ファイルから読み込み @param[out] pv データの格納場所 @param[in] cb 読み込みサイズ @param[out] pcbRead 読み出したサイズ @return HRESULT */ virtual HRESULT STDMETHODCALLTYPE Read(void* pv, ULONG cb, ULONG* pcbRead) = 0; /*! @brief ファイルポインタのシーク @param[in] lMove ファイルポインタ移動量 @param[in] dwOrigin ファイルポインタ原点 @return HRESULT */ virtual HRESULT STDMETHODCALLTYPE Seek(long lMove, DWORD dwOrigin) = 0; /*! @brief ファイルポインタのシーク @param[in] dlibMove ファイルポインタ移動量 @param[in] dwOrigin ファイルポインタ原点 @param[out] plibNewPosition 新しいファイルポインタ @return HRESULT */ virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition) = 0; /*! @brief ファイルポインタ取得 @return ファイルポインタ */ virtual long STDMETHODCALLTYPE Tell(void) = 0; /*! @brief ファイルサイズ取得 @return ファイルサイズ */ virtual long STDMETHODCALLTYPE GetSize(void) = 0; /*! @brief ファイル名取得 @return ファイル名 */ virtual const wchar_t* STDMETHODCALLTYPE GetName(void) = 0; /*! @brief ファイル情報取得 @param[out] pstatstg 情報格納先 @param[in] grfStatFlag 情報取得フラグ値 @return HRESULT */ virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG* pstatstg, DWORD grfStatFlag) = 0; /*! @brief ファイルのクローン作成 @param[out] ppstm ファイルのクローン格納先 @return HRESULT */ virtual HRESULT STDMETHODCALLTYPE Clone(IStream** ppstm) = 0; }; // **************************************************************** // // ファイルアクセスラッパ関数 // // ---------------------------------------------------------------- /*! @brief fclose互換ラッパ関数 @param[in] file IFileインターフェースのポインタ @retval 0 正常終了 @retval 0以外 エラー */ extern int CloseFileWrapper(void* file); // ---------------------------------------------------------------- /*! @brief fread互換ラッパ関数 @param[out] buffer データの格納場所 @param[in] size 項目のサイズ @param[in] count 読み出す最大項目数 @param[in] file IFileインターフェースのポインタ @return 読み取った項目の数 */ extern size_t ReadFileWrapper(void* buffer, size_t size, size_t count, void* file); // ---------------------------------------------------------------- /*! @brief fseek互換ラッパ関数 @param[in] file IFileインターフェースのポインタ @param[in] offset originからのバイト数 @param[in] origin 初期位置 @retval 0 正常終了 @retval 0以外 エラー */ extern int SeekFileWrapper(void* file, long offset, int origin); // ---------------------------------------------------------------- /*! @brief fseek64互換ラッパ関数 @param[in] file IFileインターフェースのポインタ @param[in] offset originからのバイト数 @param[in] origin 初期位置 @retval 0 正常終了 @retval 0以外 エラー */ extern int SeekFileWrapper64(void* file, __int64 offset, int origin); // ---------------------------------------------------------------- /*! @brief ftell互換ラッパ関数 @param[in] file IFileインターフェースのポインタ @retval 0以上 現在のファイル位置 @retval 0未満 エラー */ extern int TellFileWrapper(void* file); // ---------------------------------------------------------------- /*! @brief ftell64互換ラッパ関数 @param[in] file IFileインターフェースのポインタ @retval 0以上 現在のファイル位置 @retval 0未満 エラー */ extern __int64 TellFileWrapper64(void* file); // **************************************************************** }; // namespace ah // **************************************************************** // EOF
前半部分は、ファイルインターフェースの定義です。IStreamを継承しております。
IStreamのうち、Writeとかのここに書いていないメソッドは、E_NOTIMPLを返すだけの実装をします。
IStreamに、freadのように使えるReadメソッドのオーバーロードや、Tellメソッドなどが追加されています。
GetSizeでlongを返したりする辺り、2GBを超えるファイルには対応しておりません。
Statメソッドは、type/cbSize/grfModeぐらいを真面目に返せばいいよね、という実装をする予定です。
Cloneメソッドは、ファイルマッピングオブジェクトを使うことにした理由の一つ。
後半部分は、freadのように使えるラッパ関数の定義です。
fclose/fread/fseek/ftellと、fseek/ftellの64bit版です。
Ogg Vorbis用にfseekの64bit版がいるみたいなので、fseekとついでにftellには64bit版も用意しております。
fseekだけ引数64bitでも、ftellが64bit返せなければあまり意味ないと思うんだけれどなぁ。