#if defined(__FLAT__)
#ifndef _COMMON_PUREVIEWOFFILE_HPP_
#define _COMMON_PUREVIEWOFFILE_HPP_
#ifndef _COMMON_WINDOWS_HPP_
#include <common/windows.hpp>
#endif
#ifndef _COMMON_FILEMAP_HPP_
#include <common/filemap.hpp>
#endif
#ifndef _COMMON_BLOCK_HPP_
#include <common/block.hpp>
#endif
#ifndef _COMMON_PUREDWORD_HPP_
#include <common/puredwrd.hpp>
#endif

class PureViewOfFile
{
public:
	enum Access{Write=FILE_MAP_WRITE,Read=FILE_MAP_READ,Copy=FILE_MAP_COPY};
	enum SeekMethod{SeekSet,SeekCurr,SeekEnd};
  enum {CarriageReturn=0x0D,LineFeed=0x0A,NullChar=0x00};
	PureViewOfFile(void);
  PureViewOfFile(const FileMap &someFileMap,DWORD offsetHigh,DWORD offsetLow,DWORD byteCount);
	PureViewOfFile(const FileMap &someFileMap);
	virtual ~PureViewOfFile();
	PureViewOfFile &operator+=(DWORD sizeIncrement);
	PureViewOfFile &operator++(void);
	PureViewOfFile &operator-=(DWORD sizeDecrement);
	PureViewOfFile &operator--(void);
	PureViewOfFile &operator--(int postFixDummy);
	WORD seek(DWORD location,SeekMethod seekMethod=SeekCurr);
  WORD write(BYTE someByte);
	WORD write(WORD someWord);
  WORD write(short someShort);
	WORD write(int someInt);
  WORD write(double someDouble);
	WORD write(float someFloat);
	WORD write(const String &someString);
	WORD write(BYTE *npBuffer,DWORD sizeBuffer);
	WORD read(BYTE &someByte);
	WORD read(WORD &someWORD);
	WORD read(DWORD &someDWORD);
	WORD read(UINT &someUINT);
  WORD read(int &someInt);
	WORD read(double &someDouble);
	WORD read(float &someFloat);
	DWORD read(char *npBuffer,DWORD sizeBuffer);
	WORD find(const String &findString);
	WORD writeLine(const String &lineString);
	DWORD getLine(String &lineString);
	DWORD peek(BYTE *npBuffer,DWORD sizeBuffer);
	WORD peek(BYTE &someByte);
  WORD peek(int &someInt);
	DWORD tell(void)const;
	WORD push(void);
	WORD pop(void);
	DWORD base(void)const;
	DWORD size(void)const;
	WORD rewind(void);
  BOOL flush(DWORD extent);
  BOOL flush(void);
	void destroyView(void);
	void createView(const FileMap &someFileMap);
	void createView(const FileMap &someFileMap,DWORD offsetHigh,DWORD offsetLow,DWORD byteCount);
	void createView(DWORD byteCount,DWORD baseAddress);
protected:
  void *getBasePointer(void);
private:
  enum Disposition{Keep,Delete};
	PureViewOfFile(const PureViewOfFile &somePureViewOfFile);
	void *mnpCursor;
	void *mnpFirstValidAddress;
	void *mnpLastValidAddress;
  void *mnpPointer;
	Block<PureDWORD> mViewPositions;
  Disposition mDisposition;
};

inline
PureViewOfFile::PureViewOfFile(void)
: mnpCursor(0), mnpPointer(0), mnpFirstValidAddress(0), mnpLastValidAddress(0), mDisposition(Delete)
{
}

inline
PureViewOfFile::PureViewOfFile(const FileMap &someFileMap,DWORD offsetHigh,DWORD offsetLow,DWORD byteCount)
: mnpCursor(0), mnpPointer(0), mnpFirstValidAddress(0), mnpLastValidAddress(0), mDisposition(Delete)
{
  createView(someFileMap,offsetHigh,offsetLow,byteCount);
}

inline
PureViewOfFile::PureViewOfFile(const FileMap &someFileMap)
: mnpCursor(0), mnpPointer(0), mnpFirstValidAddress(0), mnpLastValidAddress(0), mDisposition(Delete)
{
	createView(someFileMap,0L,0L,someFileMap.maxExtentLow());
}

inline
PureViewOfFile::~PureViewOfFile()
{
	destroyView();
}

inline
PureViewOfFile::PureViewOfFile(const PureViewOfFile &somePureViewOfFile)
: mDisposition(Delete)
{
}

inline
PureViewOfFile &PureViewOfFile::operator+=(DWORD sizeIncrement)
{
	if((char*)mnpCursor+sizeIncrement<=mnpLastValidAddress)mnpCursor=(char*)mnpCursor+sizeIncrement;
  return *this;
}

inline
PureViewOfFile &PureViewOfFile::operator++(void)
{
  return operator+=(1L);
}

inline
PureViewOfFile &PureViewOfFile::operator-=(DWORD sizeDecrement)
{
	if((char*)mnpCursor-sizeDecrement>=mnpFirstValidAddress)mnpCursor=(char*)mnpCursor-sizeDecrement;
  return *this;
}

inline
PureViewOfFile &PureViewOfFile::operator--(void)
{
  return operator-=(1L);
}

inline
PureViewOfFile &PureViewOfFile::operator--(int /*postFixDummy*/)
{ // postfix works the same as prefix
  return operator-=(1L);
}

inline
WORD PureViewOfFile::write(WORD someWord)
{
  if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
	*((WORD*)mnpCursor)=someWord;
	mnpCursor=(char*)mnpCursor+sizeof(WORD);
	return TRUE;
}

inline
WORD PureViewOfFile::write(BYTE someByte)
{
	if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
	*((BYTE*)mnpCursor)=someByte;
	mnpCursor=(char*)mnpCursor+sizeof(BYTE);
	return TRUE;
}

inline
WORD PureViewOfFile::write(int someInt)
{
	if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
	*((int*)mnpCursor)=someInt;
  mnpCursor=(char*)mnpCursor+sizeof(int);
	return TRUE;
}

inline
WORD PureViewOfFile::write(short someShort)
{
	if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
	*((short*)mnpCursor)=someShort;
	mnpCursor=(char*)mnpCursor+sizeof(short);
  return TRUE;
}

inline
WORD PureViewOfFile::write(double someDouble)
{
	if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
	*((double*)mnpCursor)=someDouble;
	mnpCursor=(char*)mnpCursor+sizeof(double);
	return TRUE;
}

inline
WORD PureViewOfFile::write(float someFloat)
{
	if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
	*((float*)mnpCursor)=someFloat;
	mnpCursor=(char*)mnpCursor+sizeof(float);
	return TRUE;
}

inline
WORD PureViewOfFile::read(BYTE &someBYTE)
{
	if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
  someBYTE=*((BYTE*)mnpCursor);
  mnpCursor=(char*)mnpCursor+sizeof(BYTE);
	return TRUE;
}

inline
DWORD PureViewOfFile::read(char *npBuffer,DWORD sizeBuffer)
{
	if(!mnpCursor||mnpCursor>mnpLastValidAddress)return FALSE;
	if((char*)mnpCursor+(sizeBuffer-1L)>(char*)mnpLastValidAddress)
		sizeBuffer=((char*)mnpLastValidAddress-(char*)mnpCursor)+1L;
	::memcpy(npBuffer,(char*)mnpCursor,sizeBuffer);
	mnpCursor=(char*)mnpCursor+sizeBuffer;
	return sizeBuffer;
}

inline
WORD PureViewOfFile::read(WORD &someWORD)
{
	if(!mnpCursor||((char*)mnpCursor+sizeof(WORD)>mnpLastValidAddress))return FALSE;
	someWORD=*((WORD*)mnpCursor);
	mnpCursor=(char*)mnpCursor+sizeof(WORD);
	return TRUE;
}

inline
WORD PureViewOfFile::read(DWORD &someDWORD)
{
	if(!mnpCursor||((char*)mnpCursor+sizeof(DWORD)>mnpLastValidAddress))return FALSE;
	someDWORD=*((DWORD*)mnpCursor);
	mnpCursor=(char*)mnpCursor+sizeof(DWORD);
	return TRUE;
}

inline
WORD PureViewOfFile::read(UINT &someUINT)
{
	if(!mnpCursor||((char*)mnpCursor+sizeof(UINT)>mnpLastValidAddress))return FALSE;
	someUINT=*((UINT*)mnpCursor);
	mnpCursor=(char*)mnpCursor+sizeof(UINT);
	return TRUE;
}

inline
WORD PureViewOfFile::read(int &someInt)
{
	if(!mnpCursor||((char*)mnpCursor+sizeof(int)>mnpLastValidAddress))return FALSE;
	someInt=*((int*)mnpCursor);
	mnpCursor=(char*)mnpCursor+sizeof(int);
	return TRUE;
}

inline
WORD PureViewOfFile::read(double &someDouble)
{
	if(!mnpCursor||((char*)mnpCursor+sizeof(double)>mnpLastValidAddress))return FALSE;
	someDouble=*((double*)mnpCursor);
	mnpCursor=(char*)mnpCursor+sizeof(double);
	return TRUE;
}

inline
WORD PureViewOfFile::read(float &someFloat)
{
	if(!mnpCursor||((char*)mnpCursor+sizeof(float)>mnpLastValidAddress))return FALSE;
	someFloat=*((float*)mnpCursor);
	mnpCursor=(char*)mnpCursor+sizeof(float);
	return TRUE;
}

inline
WORD PureViewOfFile::peek(BYTE &someByte)
{
	if(!mnpCursor||(mnpCursor>mnpLastValidAddress))return FALSE;
	someByte=*((BYTE*)mnpCursor);
  return TRUE;
}

inline
WORD PureViewOfFile::peek(int &someInt)
{
	if(!mnpCursor||((char*)mnpCursor+sizeof(int)>mnpLastValidAddress))return FALSE;
	someInt=*((int*)mnpCursor);
  return TRUE;
}

inline
WORD PureViewOfFile::rewind(void)
{
	if(!mnpCursor)return FALSE;
	mnpCursor=mnpFirstValidAddress;
	return TRUE;
}

inline
DWORD PureViewOfFile::tell(void)const
{
	if(!mnpCursor)return FALSE;
	return (DWORD)((char*)mnpCursor-(char*)mnpFirstValidAddress);
}

inline
DWORD PureViewOfFile::base(void)const
{
	return (DWORD)mnpFirstValidAddress;
}

inline
DWORD PureViewOfFile::size(void)const
{
  return ((BYTE*)mnpLastValidAddress-(BYTE*)mnpFirstValidAddress)+1L;
}

inline
BOOL PureViewOfFile::flush(DWORD extent)
{
  return ::FlushViewOfFile(mnpFirstValidAddress,extent);
}

inline
BOOL PureViewOfFile::flush(void)
{
  return flush(size());
}

inline
WORD PureViewOfFile::push(void)
{
	PureDWORD pureDWORD(tell());
	mViewPositions.insert(&pureDWORD);
	return TRUE;
}

inline
WORD PureViewOfFile::pop(void)
{
	if(!mViewPositions.size())return FALSE;
	seek((mViewPositions[mViewPositions.size()-1].getValue()),SeekSet);
	mViewPositions.remove(mViewPositions.size()-1);
	return TRUE;
}

inline
void *PureViewOfFile::getBasePointer(void)
{
  return mnpFirstValidAddress;
}
#endif
#endif

