#include <munga.hpp>
#pragma hdrstop

#if !defined(FILESTRM_HPP)
#	include <filestrm.hpp>
#endif

//#############################################################################
//###########################    FileStream    ################################
//#############################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
FileStream::FileStream(
	const char* file_name,
	Logical writable
):
	MemoryStream(NULL, 0)
{
	Open(file_name, writable);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	FileStream::Open(
		const char* file_name,
		Logical writable
	)
{
	readOnly = !writable;
	fileHandle = -1;
	currentPosition = streamStart = NULL;
	streamSize = 0;
	if (file_name)
	{
		Check_Pointer(file_name);
		fileHandle = OpenImplementation(file_name, readOnly);
	}

	if (fileHandle != -1)
	{
		if (readOnly)
		{
			streamSize = SeekImplementation(fileHandle, 0, True);
			SeekImplementation(fileHandle, 0);
		}
		else
		{
			streamSize = 0xFFFFFFFFU;
		}
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	FileStream::Close()
{
	Check(this);

	//
	//---------------------------------
	// If the file was opened, close it
	//---------------------------------
	//
	if (fileHandle != -1)
	{
		CloseImplementation(fileHandle);
	}
	fileHandle = -1;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	FileStream::SetPointer(size_t index)
{
	Check(this);
	Verify(fileHandle != -1);

	currentPosition = (char*)SeekImplementation(fileHandle, index);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MemoryStream&
	FileStream::AdvancePointer(size_t index)
{
	Check(this);
	Verify(fileHandle != -1);

	currentPosition =
		(char*)SeekImplementation(fileHandle, (size_t)currentPosition + index);
	return *this;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MemoryStream&
	FileStream::RewindPointer(size_t index)
{
	Check(this);
	Verify(fileHandle != -1);

	currentPosition =
		(char*)SeekImplementation(fileHandle, (size_t)currentPosition + index);
	return *this;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MemoryStream&
	FileStream::ReadBytes(
		void *ptr,
		size_t number_of_bytes
	)
{
	Check(this);
	Verify(fileHandle != -1);
	Verify(readOnly);
	size_t read = ReadImplementation(fileHandle, ptr, number_of_bytes);
	Verify(read == number_of_bytes);
	currentPosition += read;
	return *this;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MemoryStream&
	FileStream::WriteBytes(
		const void *ptr,
		size_t number_of_bytes
	)
{
	Check(this);
	Verify(fileHandle != -1);
	Verify(!readOnly);
	size_t written = WriteImplementation(fileHandle, ptr, number_of_bytes);
	Verify(written == number_of_bytes);
	currentPosition += written;
	return *this;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	FileStream::TestInstance() const
{
	return True;
}

