ゲーム用のファイルシステム 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返せなければあまり意味ないと思うんだけれどなぁ。