#include"CFileReadMemory.h"
#include"../Debug/CAssert.h"

namespace Maid
{

/*!
 	@class	CFileReadMemory CFileReadMemory.h
 	@brief	メモリ上においてあるデータをファイルとして扱うクラス
 */

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

}

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

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルを開く(ポインタ先を保証しておくバージョン)
/*!
 	@param	pBegin	[i ]	読み込み開始アドレス
 	@param	Size	[i ]	読み込み範囲

	@exception CException オープンに失敗した場合
 */
void CFileReadMemory::Open( const boost::shared_array<unt08>& pBegin, int Size )
{
	OpenNoOwner( pBegin.get(), Size );
	m_pShared = pBegin;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルを開く(ポインタ先を保証しないバージョン)
/*!
 	このインスタンスがなくなるまで pBegin を解放してはいけません
 
 	@param	pBegin	[i ]	読み込み開始アドレス
 	@param	Size	[i ]	読み込み範囲
 
 	@exception CException オープンに失敗した場合
 */
void	CFileReadMemory::OpenNoOwner( const void* pBegin, int Size )
{
	MAID_ASSERT( pBegin==NULL, "引数の指定が不正です" );

	Close();

	m_pBegin = (unt08*)pBegin;
	m_Size   = Size;
	m_Position = 0;
}


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

	const int ReadSize = MySTL::min( m_Size - m_Position, Size );

	if( ReadSize<=0 ) { return 0; }

	memcpy( pData, &(m_pBegin[m_Position]), ReadSize );

	m_Position += ReadSize;

	return ReadSize;
}

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

	return m_Size;
}

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

	return m_Position;
}


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

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

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

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


}
