#include <common/fileio.hpp>

FileIO::FileIO(void)
: mlpFilePointer(0), mByteOrder(LittleEndian)
{
}

FileIO::FileIO(String pathFileName,ByteOrder byteOrder,Mode openMode,CreationFlags creationFlags)
: mlpFilePointer(0) , mByteOrder(byteOrder)
{
	open(pathFileName,byteOrder,openMode,creationFlags);
}

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

bool FileIO::close(void)
{
  if(!mlpFilePointer)return false;
  ::fclose(mlpFilePointer);
	mlpFilePointer=0;
  return true;
}

bool FileIO::open(String pathFileName,ByteOrder byteOrder,Mode openMode,CreationFlags creationFlags)
{
	close();
	if(pathFileName.isNull())return false;
	mByteOrder=byteOrder;
	if(ReadOnly==openMode)mlpFilePointer=::fopen(pathFileName,"rb");
	else 
	{
	  if(CreateAlways==creationFlags)mlpFilePointer=::fopen(pathFileName,"w+b");
		else if(Create==creationFlags)mlpFilePointer=::fopen(pathFileName,"a+b");
		else mlpFilePointer=::fopen(pathFileName,"r+b");
	}
	if(!mlpFilePointer)return false;
  return true;
}

bool FileIO::peek(BYTE &value)
{
	if(!isOkay())return false;
	read(value);
	seek(tell()-1,SeekCurrent);
  return true;
}

bool FileIO::read(BYTE &value)
{
	if(!isOkay())return false;
	return (sizeof(value)==::fread(&value,1,1,mlpFilePointer)?true:false);
}

bool 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=Intel::intelData(value);
	return true;
}

bool 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=Intel::intelData(value);
  return true;
}

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

	if(!isOkay()||!lpBuffer)return false;
	return (1==::fread(lpBuffer,lengthData,1,mlpFilePointer));
}

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

  if(!isOkay()||!lpBuffer||!lengthData)return false;
	for(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;
}

DWORD FileIO::readLine(String &lineString)
{
  int granularity(1024);
	int blockLength(granularity);
	BYTE charByte;
	BYTE *ptrLine;
	DWORD bytesRead(0);

	lineString.reserve(blockLength);
	ptrLine=(BYTE*)(char*)lineString;
	while(TRUE)
	{
	  if(!read(charByte))break;
		if(bytesRead>=blockLength-1)
		{
		  *ptrLine=0;
			String tmpString(lineString);
			int nextIndex(ptrLine-(BYTE*)(char*)lineString);
			lineString.reserve(blockLength+granularity);
			::memcpy((char*)lineString,(char*)tmpString,blockLength);
			blockLength+=granularity;
			ptrLine=(BYTE*)(char*)lineString+nextIndex;
		}
		if(CarriageReturn==charByte)
		{
		  if(!read(charByte))break;
			if(LineFeed==charByte)
			{
			  *ptrLine=0;
				return true;
			}
		}
		else if(NullChar==charByte)
		{
		  *ptrLine++=0;
			return bytesRead;
		}
		else 
		{
		  *ptrLine++=charByte;
			bytesRead++;
		}
	}
	return bytesRead;
}

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

  if(!isOkay())return false;
	if(BigEndian==mByteOrder)value=Intel::intelData(value);
	byteValue=(BYTE)(value&0x00FF);
	if(!write(byteValue))return false;
	byteValue=(BYTE)(value>>8);
  if(!write(byteValue))return false;
  return true;
}

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

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

		value=((DWORD)Intel::intelData(loWord))<<16;
		value|=Intel::intelData(hiWord);
		if(!write((char*)&value,sizeof(value)))return false;
		return true;
	}
	wordValue=(WORD)(value&0xFFFF);
	if(!write(wordValue))return false;
	wordValue=(WORD)(value>>16);
  if(!write(wordValue))return false;
  return true;
}

bool FileIO::writeLine(const String &strLine)
{
  if(!isOkay()||strLine.isNull())return false;
	if(!write((char*)(String&)strLine,strLine.length()))return false;
	return write("\r\n",2);
}

bool FileIO::write(char *lpBuffer,DWORD lengthData)
{
  if(!isOkay()||!lpBuffer||!lengthData)return false;
	if(1!=::fwrite(lpBuffer,1,lengthData,mlpFilePointer))return false;
	return true;
}

bool FileIO::rewind(void)
{
	if(!isOkay())return false;
  return (!::fseek(mlpFilePointer,0,SEEK_SET));
}

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

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

bool FileIO::seek(LONG seekOffset,SeekFrom seekFrom)
{
  if(!isOkay())return false;
	return 0==::fseek(mlpFilePointer,seekOffset,seekFrom)?true:false;
}

