#include"CFileReadFileRange.h"
#include<sys/stat.h>

#include"../Debug/CWarning.h"
#include"../Debug/CAssert.h"
#include"../Debug/CException.h"


namespace Maid
{

/*!
 	@class	CFileReadFileRange CFileReadFileRange.h
 	@brief	ファイルの特定区間を１ファイルとして扱うクラス 
 */

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

}

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

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルを開く
/*!
 	@param	FileName		[i ]	開くファイル名
 	@param	BeginPosition	[i ]	読み込み開始位置
 	@param	Size			[i ]	読み込み範囲
 
 	@exception CException オープンに失敗した場合
 */
void CFileReadFileRange::Open( const mstring& FileName, int BeginPosition, int Size )
{
	Close();

	m_hFile.Open( FileName );

	{
		//	開かれたファイルのファイルサイズを調べて　引数が大きすぎるようならエラー
		if( m_hFile.GetSize() < BeginPosition+Size )
		{
			MAID_ASSERT( true, "指定されたファイルサイズが不正です" << BeginPosition << "-" << BeginPosition+Size );
			MAID_THROWEXCEPTION(MAIDTEXT("指定されたファイルサイズが不正です"));
		}
	}

	m_BeginPosition = BeginPosition;
	m_Size     = Size;
	m_Position = 0;

	m_hFile.Seek( m_BeginPosition, IFileRead::POSITION_BEGIN );
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルを読み込む
/*!
 *	引数などは IFileRead::Read() を参照すること
 */
int CFileReadFileRange::Read( void* pData, int Size )
{
	const int ReadSize = MySTL::min(Size,m_Size-m_Position);
	const int ret = m_hFile.Read( pData, ReadSize );

	m_Position += ret;

	return ret;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルサイズの取得
/*!
 *	引数などは IFileRead::GetSize() を参照すること
 */
int CFileReadFileRange::GetSize() const
{
	return m_Size;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在のファイルポジションの取得
/*!
 *	引数などは IFileRead::GetPosition() を参照すること
 */
int CFileReadFileRange::GetPosition() const
{
	return m_hFile.GetPosition()-m_BeginPosition;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルポジションの移動
/*!
 *	引数などは IFileRead::Seek() を参照すること
 */
void CFileReadFileRange::Seek( int Size, IFileRead::POSITION ePos )
{
	int NewPos;

	switch( ePos )
	{
	case IFileRead::POSITION_BEGIN:
		{
			if( Size<0 ) { NewPos = 0;    }
			else		 { NewPos = Size; }
		}break;
	case IFileRead::POSITION_END:
		{
			if( 0<m_Size ) { NewPos = m_Size;    }
			else		   { NewPos = Size; }
		}break;

	case IFileRead::POSITION_CURRENT:
		{
			NewPos = m_Position + Size;
			if( NewPos<0		) { NewPos = 0;			}
			if( m_Size<NewPos	) { NewPos = m_Size;    }

		}break;
	}

	m_hFile.Seek( m_BeginPosition+NewPos, IFileRead::POSITION_BEGIN );
	m_Position = NewPos;
}

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


}
