
#ifndef _DDATX_H_
#define _DDATX_H_

class CDDATx
{
public:
	// 
	struct CSerializedReader {
		// 
		virtual int ReadByte() = NULL;
		// 
		virtual int ReadWord() = NULL;
	};
	// 
	struct CSurelySerializedReader {
		// 
		virtual BYTE SurelyReadByte() = NULL;
		// 
		virtual WORD SurelyReadWord() = NULL;
	};
	// 
	struct CSerializedWriter {
		// 
		virtual bool WriteByte(BYTE x) = NULL;
		// 
		virtual bool WriteWord(WORD x) = NULL;
	};
	// 
	struct CReadERR { };
	// 
	struct CFileIo : CSerializedReader, CSurelySerializedReader, CSerializedWriter {
		// 
		FILE *f;
		// 
		bool fLE;

		// 
		CFileIo(): f(NULL) { }
		// 
		~CFileIo()
		{
			Close();
		}
		// 
		void Close(bool fLE = true)
		{
			if (f) fclose(f), f = NULL;

			this->fLE = fLE;
		}
		// 
		bool OpenRead(LPCSTR psz, bool fLE)
		{
			Close(fLE);
			if (f = fopen(psz, "rb")) {
				return true;
			}
			return false;
		}
		// 
		virtual int ReadByte()
		{
			BYTE x;
			if (fread(&x, 1, 1, f) == 1) {
				return x;
			}
			return -1;
		}
		// 
		virtual int ReadWord()
		{
			BYTE x[2];
			if (fread(&x, 2, 1, f) == 1) {
				return fLE
					? MAKEWORD(x[0], x[1])
					: MAKEWORD(x[1], x[0])
				;
			}
			return -1;
		}
		// 
		virtual BYTE SurelyReadByte()
		{
			BYTE x;
			if (fread(&x, 1, 1, f) == 1) {
				return x;
			}
			throw CReadERR();
		}
		// 
		virtual WORD SurelyReadWord()
		{
			BYTE x[2];
			if (fread(&x, 2, 1, f) == 1) {
				return fLE
					? MAKEWORD(x[0], x[1])
					: MAKEWORD(x[1], x[0])
				;
			}
			throw CReadERR();
		}
	};
	// 
	struct CSerializedReaderWithChkSum : CSerializedReader
	{
		// 
		CSerializedReader &f;
		// 
		DWORD nValue;

		// 
		CSerializedReaderWithChkSum(CSerializedReader &f)
			: f(f)
			, nValue(0)
		{

		}
		// 
		int ReadByte()
		{
			int x = f.ReadByte();
			if (x < 0) return -1;
			nValue += LOBYTE(x);
			return x;
		}
		// 
		int ReadWord()
		{
			int x = f.ReadWord();
			if (x < 0) return -1;
			nValue += LOBYTE(x);
			nValue += HIBYTE(x);
			return x;
		}
	};
	// 
	struct CSerializedWriterWithChkSum : CSerializedWriter
	{
		// 
		CSerializedWriter &f;
		// 
		DWORD nValue;

		// 
		CSerializedWriterWithChkSum(CSerializedWriter &f)
			: f(f)
			, nValue(0)
		{

		}
		// 
		bool WriteByte(BYTE x)
		{
			if (!f.WriteByte(x)) return false;
			nValue += LOBYTE(x);
			return true;
		}
		// 
		bool WriteWord(WORD x)
		{
			if (!f.WriteWord(x)) return false;
			nValue += LOBYTE(x);
			nValue += HIBYTE(x);
			return true;
		}
	};
	// 
	struct CMemVuff : CSerializedWriter {
		// 
		PBYTE pData;
		// 
		int iCur, nMax;
		// 
		bool fLE;

		// 
		int ReadByte()
		{
			if (nMax < iCur + 1) return -1;

			BYTE x = pData[iCur]; iCur++;
			return x;
		}
		// 
		bool WriteByte(BYTE x)
		{
			if (nMax < iCur + 1) return false;

			pData[iCur] = x; iCur++;
			return true;
		}
		// 
		bool WriteWord(WORD x)
		{
			if (nMax < iCur + 2) return false;

			if (fLE) {
				pData[iCur] = LOBYTE(x); iCur++;
				pData[iCur] = HIBYTE(x); iCur++;
			}
			else {
				pData[iCur] = HIBYTE(x); iCur++;
				pData[iCur] = LOBYTE(x); iCur++;
			}
			return true;
		}
	};
	// 
	struct CEnclosedWisoFileIo : CSerializedReader, CSurelySerializedReader, CSerializedWriter {
		// 
		CFile &f;
		// 
		bool fLE;

		// 
		CEnclosedWisoFileIo(CFile &f, bool fLE): f(f), fLE(fLE) { }
		// 
		~CEnclosedWisoFileIo()
		{
			Close();
		}
		// 
		void Close(bool fLE = true)
		{
			this->fLE = fLE;
		}
		// 
		virtual int ReadByte()
		{
			BYTE x;
			if (f.Read(&x, 1) == 1) {
				return x;
			}
			return -1;
		}
		// 
		virtual int ReadWord()
		{
			BYTE x[2];
			if (f.Read(&x, 2) == 2) {
				return fLE
					? MAKEWORD(x[0], x[1])
					: MAKEWORD(x[1], x[0])
				;
			}
			return -1;
		}
		// 
		virtual BYTE SurelyReadByte()
		{
			BYTE x;
			if (f.Read(&x, 1) == 1) {
				return x;
			}
			throw CReadERR();
		}
		// 
		virtual WORD SurelyReadWord()
		{
			BYTE x[2];
			if (f.Read(&x, 2) == 2) {
				return fLE
					? MAKEWORD(x[0], x[1])
					: MAKEWORD(x[1], x[0])
				;
			}
			throw CReadERR();
		}
		// 
		virtual bool WriteByte(BYTE x)
		{
			TRY {
				f.Write(&x, 1);
				return true;
			} CATCH_ALL(e) {
				return false;
			} END_CATCH_ALL
		}
		// 
		virtual bool WriteWord(WORD x)
		{
			TRY {
				if (fLE) {
					BYTE v[2] = {LOBYTE(x), HIBYTE(x)};
					f.Write(v, 2);
				}
				else {
					BYTE v[2] = {HIBYTE(x), LOBYTE(x)};
					f.Write(v, 2);
				}
				return true;
			} CATCH_ALL(e) {
				return false;
			} END_CATCH_ALL
		}
	};
};

#endif // _DDATX_H_
