// DIMESerializer.h: interface for the DIMESerializer class.
//
//
// Copyright (c) 2002 Robert Cunnings. All rights reserved.
//
// You may copy, modify, distribute or publish this code free of charge.
//
// NO WARRANTY: This software is provided AS IS, without warranty of any kind.
//
//////////////////////////////////////////////////////////////////////
//
// DIMESerializer class - implementation of FSM based DIME serializer. A setup
// call to SerializeInit() establishes the record size, and subsequent calls to
// SerializeRecord() pulls one record at a time from the serializer. Finished()
// returns true when serialization is complete. CalcSerialLength()
// may be called after intialization to determine the total DIME package size
// prior to start of serialization.
//  
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DIMESERIALIZER_H__2A2F1C32_5D58_4D9D_914A_A0E7E969DCD7__INCLUDED_)
#define AFX_DIMESERIALIZER_H__2A2F1C32_5D58_4D9D_914A_A0E7E969DCD7__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "DIMEPayload.h"
#include <vector>
using namespace std;

class DIMESerializer  
{
public:

	union Header32{
		unsigned long l;
		unsigned char c[4];
	};

	enum State {
		ST_START,
		ST_OPEN_PAYLOAD,
		ST_SERIALIZE_PAYLOAD,
		ST_CLOSE_PAYLOAD,
		ST_SERIALIZE_CHUNK,
		ST_FINISH,
		ST_ERROR
	};

	enum Event {
		EV_NULL,
		EV_SERIALIZE_REC,
		EV_PAYLOAD_OPENED,
		EV_PAYLOAD_CLOSED,
		EV_PAYLOAD_END,
		EV_CHUNK_END,
		EV_MSG_END,
		EV_ERROR,
		EV_ERR_HANDLED
	};

	DIMESerializer();
	virtual ~DIMESerializer();

	bool Init(  unsigned long ulRecordSize,
				vector<DIMEPayload *> *pPayloads);
	unsigned long CalcSerialLength();
	unsigned long GetRecordSize() { return m_ulRecordSize; }
	bool SerializeRecord(	char *pszBuffer,
							unsigned long ulSize,
							unsigned long *pBytesWritten);
	bool Finished() { return m_State == ST_FINISH; }
	bool Error() { return m_State == ST_ERROR; }
	const wstring& GetLastError() { return m_wstrErrorMsg; }

protected:
	void OnEvent(Event e);
	unsigned long GetOptionsLength( DIMEPayload *pPayload,
									bool bIsFirstRecord);
	bool ProcessOptions(char *pOptions,
						unsigned long& ulLength,
						DIMEPayload *pPayload,
						bool bIsFirstRecord);

	Event ACT_Serialize_Payload();
	Event ACT_Serialize_Chunk();
	Event ACT_Open_Payload();
	Event ACT_Close_Payload();
	Event ACT_Error();

	unsigned long			m_ulRecordSize;
	unsigned long			m_ulCurrentPayload;

	vector<DIMEPayload *>	*m_pPayloads;
	State					m_State;

	char					*m_pszOutputBuffer;
	unsigned long			m_ulOutputBufferSize;
	unsigned long			m_ulOutputBytesWritten;

	wstring					m_wstrErrorMsg;

};
#define DIME_VERSION		0x08000000
#define MASK_VERSION		0xF8000000
#define MASK_TYPE_T			0x00F00000
#define MASK_MB_FLAG		0x04000000
#define MASK_ME_FLAG		0x02000000
#define MASK_CF_FLAG		0x01000000

#define HEADER_SIZE			12

#endif // !defined(AFX_DIMESERIALIZER_H__2A2F1C32_5D58_4D9D_914A_A0E7E969DCD7__INCLUDED_)
