
/*!
@since 2003/10/17
@auther d金魚
@note
Licence is BSD Licence

*/


#ifndef _dkutilFSWin32Common__h_
#define _dkutilFSWin32Common__h_

#ifdef USE_DKINGYO_INCLUDE_SETTING_LIKE_BOOST
#	include <dkutil/dkutilDefined.h>
#	include <dkutil/dkutilString.h>
#else
#	include "dkutilString.h"
#	include "dkutilDefined.h"
#endif

namespace dkutil{
		

/// パス名から、拡張子の開始位置を取得する
/// ファイル名の末尾からファイル名の最後の '.' までを、拡張子と判断する
///@return NULLだと拡張子は判別不能。また、与えられた文字列の最初のアドレスが返された場合も判別不能
///
inline char *GetFileExtension( const char *PathName )
{

	char *p;
	char *get_tail;

	get_tail = strtail( PathName );
	for( p = get_tail; p >= PathName; p-- ) // 文字列の最後から最初まで
	{
		if ( ('\\'==*p) && !isJMS(PathName,p-PathName) )
			return get_tail; // ファイル名はここまで

		if ( '.' == *p )
			return p+1; // '.' を発見
	}
	return get_tail; // 拡張子なし
}//GetFileExtension



///ファイルサイズを得る。
/*!
@param str[in] ファイルの名前(パス）
@param high[out] ファイルのサイズの上位ダブルワード(これにMAXDWORDをかけてlowを足すとファイルサイズになる。
@param low[out] ファイルサイズの下位ダブルワード
*/
///ファイルサイズを得る。ロックされたファイルでも得ることが出来るので便利＾＾；
inline bool GetFileSizeHighLow(const char *str,DWORD *high,DWORD *low){
	WIN32_FIND_DATA findData={0};
	HANDLE hFind=NULL;
	// ファイルサイズ取得
	if((hFind = FindFirstFile(str,&findData)) == INVALID_HANDLE_VALUE){
		return false;
	}

	//ファイルのサイズをヴちこむ
	*high = findData.nFileSizeHigh;
	*low = findData.nFileSizeLow;
	FindClose(hFind);
	return true;
}
/*!
@param str[in] ファイルの名前(パス）
@param  *GetSize[out] ファイルのサイズを入れるULONGLONG型の変数へのポインタ
*/
///ファイルサイズを得る。dGetFileSizeHighLowのラッパー
inline bool GetFileSize(const char *str,ULONGLONG *GetSize){
	DWORD High=0,Low=0;
	bool result=false;
	result=GetFileSizeHighLow(str,&High,&Low);
	*GetSize = ( High * MAXDWORD ) + Low;
	return result;
}

/*!
注意：約４GB以下のファイルサイズを得ることが出来る。ULONG_MAX byteですかね？<br>
@return 成功したらファイルサイズを返す。0だとdGetFileSize関数が失敗した,または約4GB以上（ ULONG_MAX byte以上)のファイルのことを表す。
*/
///ファイルサイズを得る（dGetFileSizeのラッパー)　ULONG_MAX byte以下のファイル専用
inline DWORD GetFileSizeMini(const char *str){
	ULONGLONG Get;
	if(false==GetFileSize(str,&Get)) return 0;
	if(ULONG_MAX < Get) return 0;
	return static_cast< DWORD >(Get);
}

/*!

@param data[in] ファイルのデータへのポインタ(void *)にキャストしてぶち込んでください。
@param size[in] ファイルのデータのサイズ　(書き込むサイズ)
@param fname[in] ファイルの名前
@param mode[in] デフォルトで="wb" オープンモード 詳しくはMSDNのfopen関数を見よ！
@return true=成功 false=失敗

*/
///fopenのファイル関数を使ってバイナリセーブを行う。
inline bool SaveBinary(void *data,int size,char *fname,char *mode="wb"){//="wb"
	FILE *fp;
	fp = fopen( fname , mode ) ;//wb
	if(fp==NULL) return false;
	fwrite( data , size  , 1 , fp ) ;
	//fwrite( data , sizeof(size)  , 1 , fp ) ;
	fclose( fp ) ;
	return true;
}

/*!
@param data[out] ファイルのデータのバッファ (void *)にキャストしてぶち込んでください。
@param size[in] ファイルのデータのバッファサイズ　(読み込むサイズ)
@param fname[in] ファイルの名前
@param mode[in] デフォルトで="rb" オープンモード 詳しくはMSDNのfopen関数を見よ！
@return true=成功 false=失敗
*/
///バイナリデータをメモリに読み込む。SaveBinary()と対
inline bool LoadBinary(void *data,int size,char *fname,char *mode ){//="rb"
	FILE *fp ;
	fp = fopen( fname , mode ) ;//rb
	if(fp==NULL)return false;
	fread( data ,  size , 1 , fp ) ;
	//fread( data , sizeof(size)  , 1 , fp ) ;
	fclose( fp ) ;
	return true;
}
	
/*!
Win32APIのファイル系関数を使ってセーブ、ロードを行う。
@param filename[in] ファイルネーム 例："sample.txt" 等
@param filedata[in] ファイルのデータ
@param size[in] ファイルのデータのサイズ(バイト単位)
@return edk_SUCCEEDED以外だったらエラー
@note
GetLastError()でエラー情報を取得できます。

*/ 
extern int SaveFile(const char *filename,const void *filedata,size_t size);

/*!
@param filename[in] ファイルネーム 例："sample.txt" 等
@param filedata[in] ファイルのデータ
@param size[in] ファイルのデータのサイズ(バイト単位)
@param GetReadSize[in] 実際に読み込んだサイズ
@return edk_SUCCEEDED以外だったらエラー
@note
GetLastError()でエラー情報を取得できます。<br>
注意：エラーの場合、この戻り値をあまり信用しないで、VISUAL_LASTERROR()等のマクロを使ってみてください。<br>

*/
extern int LoadFile(const char *filename,void *Buff,size_t BuffSize,DWORD *GetReadSize);
	
/*!
☆データセーブ:<br>
データをちょっと暗号化してセーブをします。<br>
なので、バイナリエディタで開いても一見分かりません。<br>
@param	*pFile[in]			: データ名
@param	*pData[out]			: データへのポインタ
@param	Size[in]	: データサイズ
@return	 成功 true / 失敗 false
*/
extern bool SaveData( char *pFile, void *pData, unsigned long Size );
/*!
☆データロード:dkutil::SaveData()で保存したデータロードをします。
@param *pFile[in]			: データ名
@param *pData[out]			: データへのポインタ
@param Size[in]	: データサイズ
@return : 成功 true / 失敗 false

*/
extern bool LoadData( char *pFile, void *pData, unsigned long Size );



///ファイルのみ検索のはず！！
inline bool FileExist(const char *s){
	return (::GetFileAttributes(s) != 0xFFFFFFFF);
}
/*!
☆ファイル存在チェックファイルの存在チェックをします。
@param	 *pFile[in]		: チェックするファイル名
@return 存在する＝true / 存在しない = false
@note
フォルダも検索されちゃうかも！？
*/
inline bool FileAndFolderExist( const char *pFile )
{
	WIN32_FIND_DATA wfd;
	//  ファイル検索ハンドルを取得
	HANDLE hFile = ::FindFirstFile( pFile, &wfd );
	// 検索できたかチェック
	bool bRet = (hFile != INVALID_HANDLE_VALUE);
	// 検索ハンドルをクローズ
	::FindClose( hFile );
	return bRet;
}
/*!
☆フォルダ生成フォルダの生成をします。
@param	 *pPath[in]		: 生成フォルダパス
@return	: 成功 true / 失敗 false
*/
extern bool CreateDirectory( const char *pPath );



/*!
	☆CDのボリュームラベル検索:<br>
	任意のボリュームラベルを持つＣＤを検索します。<br>
@param		*pLabel[in]	: 検索するボリュームラベル
@param		*pPath[in]		: 検索対象のボリュームラベルを持つドライブの格納先

@return				: 成功 true / 失敗 false
*/
extern bool CheckCDVolumeLabel( char *pLabel, char *pPath ,size_t pPathSize);

/*!
☆ファイルコピー:<br>
	ファイルコピーを行います。<br>
	ファイル属性が通常になりますので、
	CDからコピーされた場合は読取専用が
	解除されます。<br>
@param	*pSrc[in]	: コピー元
@param	*pDst[in]	: コピー先
@param bRewrite[in] trueだと、上書きします。
@return : 成功 true / 失敗 false
*/
inline bool CopyFileFromCD( LPCTSTR pSrc, LPCTSTR pDst ,bool bRewrite=false){
	//	 コピー
  if ( ::CopyFile( pSrc, pDst, !(bRewrite) ) )
	{
	// ファイル属性を通常にする
      return (::SetFileAttributes( pDst, FILE_ATTRIBUTE_NORMAL ) != false);
  }
  return false;
}

inline bool CheckDrive(BYTE c){
	DWORD drive = ::GetLogicalDrives();
	if(!isAlpha(c)) throw std::invalid_argument("文字定数入れろっツーの！");
	c =(BYTE) tolower((int)c);
	c -= 'a';
	DWORD mask =(DWORD)pow(2,c);
	if(drive & mask){
		return true;
	}
	return false;
}

}//end of dkutil namespace








#endif //end of include once 
