#include <common/fileio.hpp>

FileIO::FileIO(void)
: mFileDescriptor(InvalidFile), mByteOrder(LittleEndian), mInputBuffer(MaxInputBuffer),
	mOpenMode(ReadOnly)
{
}

FileIO::FileIO(String pathFileName,ByteOrder byteOrder,Mode openMode)
: mFileDescriptor(InvalidFile), mByteOrder(byteOrder), mInputBuffer(MaxInputBuffer),
	mOpenMode(openMode)
{
  if(!mInputBuffer.lpBuffer())return;
	open(pathFileName);
}

FileIO::~FileIO()
{
	close();
}

WORD FileIO::close(void)
{
	if(InvalidFile==mFileDescriptor)return FALSE;
	::close(mFileDescriptor);
	mFileDescriptor=InvalidFile;
  return TRUE;
}

WORD FileIO::open(String pathFileName,Mode openMode,CreationFlags creationFlags)
{
	close();
	mOpenMode=openMode;
	if(ReadOnly==mOpenMode)mFileDescriptor=::open(pathFileName,O_RDONLY|O_BINARY,S_IREAD);
	else mFileDescriptor=::open(pathFileName,O_RDWR|O_BINARY|creationFlags,S_IREAD|S_IWRITE);
	if(InvalidFile==mFileDescriptor)return FALSE;
  return TRUE;
}

WORD FileIO::read(BYTE &value)
{
	if(!isOkay())return FALSE;
	if(ReadOnly==mOpenMode)
	{
		if(!mInputBuffer.bufferIndex())
		{
			mInputBuffer.bufferIndex(::read(mFileDescriptor,mInputBuffer.lpBuffer(),MaxInputBuffer));
			if(!mInputBuffer.bufferIndex())return FALSE;
		}
		value=*(mInputBuffer.lpBufferPointer());
		++mInputBuffer;
	}
	else if(0>=::read(mFileDescriptor,&value,1))return FALSE;
  return TRUE;
}

WORD FileIO::read(WORD &value)
{
  BYTE byteValue;

	if(!isOkay())return FALSE;
	if(!read(byteValue))return FALSE;
	value=byteValue;
	if(!read(byteValue))return FALSE;
  value|=((WORD)byteValue)<<8;
	if(BigEndian==mByteOrder)value=mIntelData.intelData(value);
	return TRUE;
}

WORD FileIO::read(DWORD &value)
{
	WORD wordValue;

	if(!isOkay())return FALSE;
	if(!read(wordValue))return FALSE;
	value=wordValue;
	if(!read(wordValue))return FALSE;
	value|=((DWORD)wordValue)<<16;
	if(BigEndian==mByteOrder)value=mIntelData.intelData(value);
  return TRUE;
}

WORD FileIO::read(char *lpBuffer,WORD lengthData)
{
	BYTE byteValue;

	if(!isOkay())return FALSE;
	for(WORD index=0;index<lengthData;index++)
	{
		if(!read(byteValue))return FALSE;
    *(lpBuffer++)=byteValue;
	}
  return TRUE;
}

WORD FileIO::read(char *lpBuffer,WORD lengthData,int stopChar)
{
	BYTE tempChar;

	for(int bytesRead=0;bytesRead<lengthData-1;bytesRead++)
	{
		if(!read(tempChar))return FALSE;
		if(tempChar==stopChar)break;
		*(lpBuffer++)=tempChar;
	}
  *(lpBuffer)=0;
  if(!bytesRead)return FALSE;
	return TRUE;
}

WORD FileIO::write(WORD value)
{
	BYTE byteValue;

  if(!isOkay())return FALSE;
	if(BigEndian==mByteOrder)value=mIntelData.intelData(value);
	byteValue=(BYTE)(value&0x00FF);
	if(!write(byteValue))return FALSE;
	byteValue=(BYTE)(value>>8);
  if(!write(byteValue))return FALSE;
  return TRUE;
}

WORD FileIO::write(DWORD value)
{
	WORD wordValue;

	if(!isOkay())return FALSE;
	if(BigEndian==mByteOrder)
	{
		WORD hiWord(HIWORD(value));
		WORD loWord(LOWORD(value));

		value=((DWORD)mIntelData.intelData(loWord))<<16;
		value|=mIntelData.intelData(hiWord);
		write((char*)&value,sizeof(value));
		return TRUE;
	}
	wordValue=(WORD)(value&0xFFFF);
	write(wordValue);
	wordValue=(WORD)(value>>16);
  write(wordValue);
  return TRUE;
}

WORD FileIO::write(char *lpBuffer,WORD lengthData)
{
  if(!isOkay())return FALSE;
	if(!lengthData)return TRUE;
	if(-1==::write(mFileDescriptor,lpBuffer,lengthData))return FALSE;
	return TRUE;
}

FileIO &FileIO::operator++(void)
{
	seek(1L,SeekCurrent);

	return *this;
}

FileIO &FileIO::operator--(void)
{
	seek(-1L,SeekCurrent);
  return *this;
}

WORD FileIO::seek(LONG seekOffset,SeekFrom seekFrom)
{
	if(!isOkay())return FALSE;
	if(-1==::lseek(mFileDescriptor,seekOffset,seekFrom))return FALSE;
  mInputBuffer.bufferIndex(0);
  return TRUE;
}

WORD FileIO::rewind(void)
{
	if(!isOkay())return FALSE;
  if(!seek(0L,SeekBeginning))return FALSE;
  return TRUE;
}





