#pragma once

#include <exception>
#include <vector>
#include <iterator>

/*!
 * ファイル入出力の例外
 */
class CFileIOException
	: public std::exception
{
private:
	DWORD errorcode_;

public:
	CFileIOException(DWORD errorcode);

	DWORD GetErrorCode() const;
};


/*!
 * UNICODE/MBCSの双方の読み込み・書き込みをtstringでできるようにするためのクラス
 */
class CFileIO
{
private:
	tstring fname_;

	HANDLE hFile_;

	bool eof_;

	bool unicode_;

	bool wrote_;

	typedef std::vector<unsigned char> rawbuffer;

	rawbuffer buf_;

	rawbuffer::iterator pt_, endpt_;

	rawbuffer::value_type pch_;

	CFileIO(const CFileIO&); //<! 実装なし

	CFileIO& operator=(const CFileIO&); //<! 実装なし

public:

	/*!
	 * ファイル名を指定して構築します。
	 */
	CFileIO(const tstring& fname);

	/*!
	 * ファイルがまだ開いていれば閉じます。
	 */
	~CFileIO() throw();

	/*!
	 * 読み込みまたは書き込みモードで開きます。
	 * 読み込みモードではファィルのオープンに失敗した場合はfalseを返します。
	 * 書き込みモードの場合、ファイルのオープンに失敗した場合はCFileIOException例外が発生します。
	 * 書き込みモードでオープンできた場合、既存のファイルのサイズはゼロになります。
	 * 読み込みモードの場合、ファイルの先頭にUTF-16のBOMがあるか読み取りモードを設定します。
	 * BOMの読み取りに失敗した場合はCFileIOException例外が発生します。
	 * \param save trueならば書き込みモード
	 */
	bool Open(bool save);

	/*!
	 * ファイルを明示的に閉じます。
	 * ファイルのクローズに失敗しても例外は返しません。
	 */
	void Close() throw();
	
	/*!
	 * 読み込みモード時、対象ファイルがUNICODEであればtrueを返します。
	 * \return 対象ファイルのBOMがUNICODEであればtrue
	 */
	bool IsUnicode() const;

	/*!
	 * ファイルにテキストを書き込みます。
	 * UNICODEビルドであればUTF-16、そうでなければMBCSで書き込まれます。
	 * UNICODEビルドの最初の書き込みでBOMも書き込まれます。
	 * \param line 書き込み行
	 */
	void PutText(tstring& line);

	/*!
	 * ファイルから１行読み取ります。
	 * LFまでが１行となります。(もしくはEOF)
	 * 返される行にCR/LFは除去されます。
	 * 行の長さ制限はありません。
	 * ファイルがUNICODE/MBCSどちらであってもtstringで返されます。
	 * ファイルの読み取りエラーが発生した場合、もしくはUNICODEとMBCSの変換に失敗した場合は
	 * CFileIOException例外が発生します。
	 * EOFに達した場合の次の読み込みではlineは空となり戻り値はfalseとなります。
	 * \param line 書き込まれる行
	 * \return 行が読み取れた場合はtrue、終端に達した場合はfalse
	 */
	bool GetText(tstring& line);

private:
	/*!
	 * 初期化
	 */
	void Init() throw();

	/*!
	 * ファイルのBOMを読み取り、BOMの次の位置に位置づけます。
	 * BOMがない場合はファイルの先頭に位置づけます。
	 */
	void CheckUnicode();
};


