////////////////////////////////////////////////////////////////////////////
// CFD クラスのインプリメンテーション
//
////////////////////////////////////////////////////////////////////////////

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string>

#include "FD.h"

using namespace std;
using namespace NNabikiVPtr;

////////////////////////////////////////////////////////////////////////////
// 構築/破棄
////////////////////////////////////////////////////////////////////////////

CFD::CFD() :
	fd( -1 )
{

}

CFD::~CFD()
{
	Close();
}

////////////////////////////////////////////////////////////////////////////
// メソッド
////////////////////////////////////////////////////////////////////////////

// 開く
bool CFD::Open( const char *pFName, int flg, int mode )
{
	assert( NULL != pFName && NULL != this );

	// すでに開いていたら、一旦閉じる
	if ( fd >= 0 ) Close();

	// 開く
	fd = open( pFName, flg, mode );
	if ( fd < 0 ) return false;
	return true;
}

// 書き込む
bool CFD::Write( const void *pBuf, int len ) const
{
	if ( fd < 0 ) return false;

	return write( fd, pBuf, len ) == len;
}


// ブロックするまでデータを読み込む
VPtr< char > CFD::Read() const
{
	VPtr< char > pRetBuf;
	string wStr;
	char Buf[512];
	const int BufLen = sizeof( Buf ) / sizeof( Buf[0] );
	int len;

	if ( fd < 0 )
		return VPtr< char >( NULL );

	if ( fcntl( fd, F_SETFL, O_NONBLOCK ) )
		return VPtr< char >( NULL );

	// データを読み込む
	wStr = "";
	len = read( fd, Buf, BufLen );
	while ( len > 0 ) {
		wStr += string( Buf, len );
		len = read( fd, Buf, BufLen );
	}

	// 戻り値用のバッファを確保
	if ( !pRetBuf.Malloc( sizeof( char ) * wStr.length() ) )
		return VPtr< char >( NULL );
	memcpy( pRetBuf.GetPtr(), wStr.c_str(), wStr.length() );

	return pRetBuf;
}

// 読み込む
int CFD::Read( void *pBuf, int len ) const
{
	if ( fd < 0 ) return -1;
	return read( fd, pBuf, len );
}

// 閉じる
void CFD::Close()
{
	assert( NULL != this );

	// すでに閉じていたら、特にすることはない
	if ( fd < 0 ) return ;

	close( fd );
	fd = -1;
}

// ディスクリプタの取得
CFD::operator int() const
{
	return fd;
}

