#include"CFileReadNormal.h"
#include<sys/stat.h>
#include"../CString.h"
#include"../Debug/CAssert.h"
#include"../Debug/CException.h"
#include"../Debug/CWarning.h"


namespace Maid
{
/*!
 	@class	CFileReadNormal CFileReadNormal.h
 	@brief	通常のファイル読み込みクラス
\n			ライブラリはＣランタイムを使っています。
\n			このクラスを使うよりも CFileRead を使ったほうが便利です
 
 */


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 */
CFileReadNormal::CFileReadNormal() 
	: m_Handle(NULL), m_Size(0), m_Position(0)
{

}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! デストラクタ
/*!
 */
CFileReadNormal::~CFileReadNormal()
{
	Close();
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルを開く
/*!
	@param	FileName [i ]	開くファイル名

	@exception CException オープンに失敗した場合
 */
void CFileReadNormal::Open( const mstring& FileName )
{
	Close();

	MySTL::string str = CString::ConvertMAIDtoSJIS(FileName);

	m_Handle = ::fopen( str.c_str(), "rb" );

	if( m_Handle==NULL )
	{
		MAID_ASSERT( true, "ファイルのオープンに失敗" << FileName );
		MAID_THROWEXCEPTION(MAIDTEXT("ファイルのオープンに失敗"));
	}

	//	ファイルサイズを調べる
	struct stat StatFile; 
	::fstat( ::fileno(m_Handle), &StatFile );

	m_Size     = StatFile.st_size;
	m_Position = 0;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルを読み込む
/*!
 	引数などは IFileRead::Read() を参照すること
 */
int CFileReadNormal::Read( void* pData, int Size )
{
	MAID_ASSERT( m_Handle==NULL, "ファイルが開かれていません" );

	if( Size==0 ) { return 0; }
	//	ファイルの末端を越えないように読み込む
	int ReadSize;
	
	if( m_Position+Size>m_Size )	{ ReadSize = m_Size-m_Position; }
	else							{ ReadSize = Size; }

	::fread( pData, ReadSize, 1, m_Handle );

	m_Position += ReadSize;


	return ReadSize;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルサイズの取得
/*!
 	引数などは IFileRead::GetSize() を参照すること
 */
int CFileReadNormal::GetSize() const
{
	MAID_ASSERT( m_Handle==NULL, "ファイルが開かれていません" );
	return m_Size;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在のファイルポジションの取得
/*!
 	引数などは IFileRead::GetPosition() を参照すること
 */
int CFileReadNormal::GetPosition() const
{
	MAID_ASSERT( m_Handle==NULL, "ファイルが開かれていません" );
	return m_Position;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルポジションの移動
/*!
 	引数などは IFileRead::Seek() を参照すること
 */
void CFileReadNormal::Seek( int Size, IFileRead::POSITION ePos )
{
	MAID_ASSERT( m_Handle==NULL, "ファイルが開かれていません" );

	long Origin;
	switch( ePos )
	{
	case IFileRead::POSITION_BEGIN:		{ Origin = SEEK_SET; }break;
	case IFileRead::POSITION_END:		{ Origin = SEEK_END; }break;
	case IFileRead::POSITION_CURRENT:	{ Origin = SEEK_CUR; }break;
	}
	
	::fseek( m_Handle, Size, Origin );

	m_Position = ::ftell( m_Handle );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 開いているファイルを閉じる
/*!
 	引数などは IFileRead::Close() を参照すること
 */
void CFileReadNormal::Close()
{
	if( m_Handle!=NULL )
	{
		::fclose( m_Handle );
		m_Handle  = NULL;
		m_Size    = 0;
		m_Position= 0;
	}
}

}
