// $Id: SerializationFormat.h,v 1.1 2003/08/31 00:38:11 vern Exp $
//
// Implements different data formats for serialization.

#ifndef SERIALIZATION_FORMAT
#define SERIALIZATION_FORMAT

#include "util.h"

// Abstract base class.
class SerializationFormat {
public:
	SerializationFormat();
	virtual ~SerializationFormat();

	// Unserialization.
	virtual void StartRead(char* data, uint32 len);
	virtual void EndRead();

	virtual bool Read(int* v) = 0;
	virtual bool Read(uint32* v) = 0;
	virtual bool Read(char* v) = 0;
	virtual bool Read(bool* v) = 0;
	virtual bool Read(double* d) = 0;

	// Passes ownership of string.
	virtual bool Read(char** str, int* len) = 0;

	// Serialization.
	virtual void StartWrite();
	virtual uint32 EndWrite(char** data);	// passes ownership

	virtual void Write(int v, const char* tag) = 0;
	virtual void Write(uint32 v, const char* tag) = 0;
	virtual void Write(char v, const char* tag) = 0;
	virtual void Write(bool v, const char* tag) = 0;
	virtual void Write(double d, const char* tag) = 0;
	virtual void Write(const char* s, const char* tag) = 0;
	virtual void Write(const char* buf, int len, const char* tag) = 0;

	virtual void WriteOpenTag(const char* tag) = 0;
	virtual void WriteCloseTag(const char* tag) = 0;
	virtual void WriteSeparator() = 0;

protected:
	bool ReadData(void* buf, size_t count);
	void WriteData(const void* buf, size_t count);

	static const int INITIAL_SIZE = 256;
	char* buffer;

	uint32 len;
	uint32 pos;
	bool own;	// do we have to delete the buffer?
};

class BinarySerializationFormat : public SerializationFormat {
public:
	BinarySerializationFormat();
	virtual ~BinarySerializationFormat();

	virtual bool Read(int* v);
	virtual bool Read(uint32* v);
	virtual bool Read(char* v);
	virtual bool Read(bool* v);
	virtual bool Read(double* d);
	virtual bool Read(char** str, int* len);
	virtual void Write(int v, const char* tag);
	virtual void Write(uint32 v, const char* tag);
	virtual void Write(char v, const char* tag);
	virtual void Write(bool v, const char* tag);
	virtual void Write(double d, const char* tag);
	virtual void Write(const char* s, const char* tag);
	virtual void Write(const char* buf, int len, const char* tag);
	virtual void WriteOpenTag(const char* tag);
	virtual void WriteCloseTag(const char* tag);
	virtual void WriteSeparator();
};

class XMLSerializationFormat:public SerializationFormat {
public:
	XMLSerializationFormat();
	virtual ~ XMLSerializationFormat();

	// We don't write anything if tag is nil.
	virtual void Write(int v, const char* tag);
	virtual void Write(uint32 v, const char* tag);
	virtual void Write(char v, const char* tag);
	virtual void Write(bool v, const char* tag);
	virtual void Write(double d, const char* tag);
	virtual void Write(const char* s, const char* tag);
	virtual void Write(const char* buf, int len, const char* tag);
	virtual void WriteOpenTag(const char* tag);
	virtual void WriteCloseTag(const char* tag);
	virtual void WriteSeparator();

	// Not implemented.
	virtual bool Read(int* v);
	virtual bool Read(uint32* v);
	virtual bool Read(char* v);
	virtual bool Read(bool* v);
	virtual bool Read(double* d);
	virtual bool Read(char** str, int* len);

private:
	// Encodes non-printable characters.
	void WriteEncodedString(const char* str, int len);

	// Write an elment including type and encoding.
	void WriteElem(const char* tag, const char* type,
				   const char* content, int len);
};

#endif
