#ifndef _CDEV_PACKET_BINARY_H_
#define _CDEV_PACKET_BINARY_H_

#include <cdevPacketBinary.h>

// *****************************************************************************
// * OperationCode Definitions :
// *	CDEV_NORMAL_OP = 0 : This is a message that is to be processed by the
// *	                     developer's server interface.
// *	CDEV_SERVER_OP = 1 : This is a message that is to be processed by the
// *	                     Generic Server Interface.
// *****************************************************************************
enum	{
	CDEV_NORMAL_OP = 0,
	CDEV_SERVER_OP = 1
	};
	
// *****************************************************************************
// * struct cdevMessageBinaryMap :
// *	This is the first 32 bit integer that is passed through the socket.  It
// *	contains a bitmap that identifies the version of the packet, as well as
// *	a bit field that indicates the contents of the packet.  This bitfield
// *	simplifies the process of decoding the packet and results in a smaller
// *	transmission size.
// *****************************************************************************
typedef union
	{
	unsigned rawData;
	struct  {
		unsigned version             : 16;
		unsigned clientIDSet         : 1;
		unsigned transIndexSet       : 1;
		unsigned cancelTransIndexSet : 1;
		unsigned localDataIndexSet   : 1;
		unsigned foreignDataIndexSet : 1;
		unsigned operationCodeSet    : 1;
		unsigned completionCodeSet   : 1;
		unsigned deviceListSet       : 1;
		unsigned messageSet          : 1;
		unsigned dataSet             : 1;
		unsigned contextSet          : 1;
		unsigned tagMapSet           : 1;
		unsigned pad                 : 4;
		} value;
	} cdevMessageBinaryMap;


// *****************************************************************************
// * The following elements are contained within a cdevMessageBinary binary 
// * object.
// * 
// * short     version          : This is the version of the cdevPacketBinary 
// *				  that is being constructed.  The format and 
// *				  structure of the remainder of the data is 
// *				  based on version 1.
// *
// * short     clientID         : **** REQUIRED ****
// *                              This is the clientID that the server will use
// *                              to uniquely identify this client.  
// *
// * unsigned  transIndex       : **** REQUIRED ****
// *                              This is the index that will be used on the
// *                              client side to locate the transaction object
// *                              associated with this request.
// *
// *
// * unsigned  cancelTransIndex : This is the transaction index of a transaction
// *                              that should be canceled.  This field is
// *                              typically used to terminate a monitor.
// *
// * unsigned  localDataIndex   : This is the index that will be used on the
// *                              ~packet senders~ side to identify a list
// *                              of devices.
// *
// * unsigned  foreignDataIndex : This is the index that will be used on the
// *                              ~packet receivers~ side to identify a list
// *                              of devices.
// *
// *
// * unsigned operationCode     : This is a user defined operation code that
// *                              may be used to reduce the size of the data
// *                              that is transmitted between the client and 
// *                              the server by using integer operation codes
// *                              rather than character strings.
// *
// * int completionCode         : This is the result of the operation on the
// *                              server side.
// *
// * unsigned  deviceCount      : This is the number of device names that will
// *                              be contained in the following list.
// *
// * char   ** deviceList       : This is a list of character strings that 
// *                              identify cdevDevices.
// *
// * char   *  message          : This is the message text.
// *
// * cdevData  data             : This is a cdevData object containing the
// *                              data associated with the request or
// *                              the result of the request if this packet
// *                              is a response from a server.
// *
// * cdevData  context          : This is a cdevData object specifying the
// *                              context of the request.
// *
// * cdevData  tagMap           : This is a cdevData object that contains the
// *                              mapping of the cdevData tag table for the 
// *                              client.  By virtue of the fact that this table
// *                              cannot rely on any of the known tags to exist
// *                              of be the same... the following integer values
// *                              will be used.
// *
// *                              1)  An array of integers that identify the
// *                                  tag numbers.
// *
// *                              2)  An array of strings that identify the
// *                                  tag names.
// *
// *****************************************************************************
class GENERIC_SERVER_API cdevMessageBinary : public cdevPacketBinary
{
private:
	cdevMessageBinaryMap map;
	XDR_Reader           reader;
	
		
protected:
	typedef enum 
		{
		GOTO_CLIENTID=1,
		GOTO_TRANSINDEX,
		GOTO_CANCELTRANSINDEX,
		GOTO_LOCALDATAINDEX,
		GOTO_FOREIGNDATAINDEX,
		GOTO_OPERATIONCODE,
		GOTO_COMPLETIONCODE,
		GOTO_DEVICELIST,
		GOTO_MESSAGE,
		GOTO_DATA,
		GOTO_CONTEXT,
		GOTO_TAGMAP} POSITION_FLAG;

	// *********************************************************************
	// * cdevMessageBinary::setBinaryPosition :
	// *	This method will set the position of the binary stream within an 
	// *	XDR_Reader to the specified data object.
	// *	This method returns 0 on success, or -1 if the data object could 
	// *	not be selected.
	// *********************************************************************
	int setBinaryPosition (XDR_Reader & reader, POSITION_FLAG flag );

public:
	enum { CDEV_PACKET_VERSION = 2 };

	cdevMessageBinary ( cdevMessageBinary &packet );
	cdevMessageBinary ( short            clientID         = -1, 
		            unsigned         transIndex       = 0, 
                            unsigned         cancelTransIndex = 0,
		            unsigned         localDataIndex   = 0, 
		            unsigned         foreignDataIndex = 0,
		            unsigned         operationCode    = 0,
		            int              completionCode   = 0,
		            unsigned         deviceCount      = 0,
		            char **          deviceList       = NULL,
		            char *           message          = NULL,
		            cdevData *       data             = NULL,
		            cdevData *       context          = NULL,
		            cdevData *       tagMap           = NULL );	
	
	virtual ~cdevMessageBinary ( void );
	
	// *********************************************************************
	// * map2int ( void )
	// *	This method will convert the cdevMessageBinaryMap to an unsigned
	// *********************************************************************
	unsigned map2int ( cdevMessageBinaryMap map, unsigned & value);

	// *********************************************************************
	// * int2map ( void )
	// *	This method will convert an unsigned to a cdevMessageBinaryMap.
	// *********************************************************************
	cdevMessageBinaryMap int2map ( cdevMessageBinaryMap &map, unsigned value);
	
	// *********************************************************************
	// * The streamIn function will populate the cdevMessageBinary using the 
	// * data that is specified in the stream.  The stream remains the 
	// * property of the caller, who must delete it when it is no longer 
	// * needed.
	// *********************************************************************
	virtual int  streamIn  ( char * stream, size_t len );
	
	// *********************************************************************
	// * attachData :
	// *	This method allows the caller to assign a preallocated binary
	// *	buffer to this object.  This prevents the cdevMessageBinary class
	// *	from having to allocate the data.
	// *********************************************************************
	int attachData ( char * stream, size_t len );

	// *********************************************************************
	// * Performs a diagnostic dump of the object.
	// *********************************************************************
	virtual void asciiDump ( FILE * fp = stdout );

	// *********************************************************************
	// * The set mechanism: 
	// *	Allows the caller to dynamically change the contents of the
	// *	binary structure.
	// *********************************************************************
	void set ( short            clientID         = -1, 
		   unsigned         transIndex       = 0,
		   unsigned         cancelTransIndex = 0, 
		   unsigned         localDataIndex   = 0, 
		   unsigned         foreignDataIndex = 0,
		   unsigned         operationCode    = 0,
		   int              completionCode   = 0,
		   unsigned         deviceCount      = 0,
		   char **          deviceList       = NULL,
		   char *           message          = NULL,
		   cdevData *       data             = NULL,
		   cdevData *       context          = NULL,
		   cdevData *       tagMap           = NULL );	

	// *********************************************************************
	// * The get mechanisms:
	// *	The pointers that are retrieved by these functions are the
	// *	actual pointers that are used within the class.  They should not
	// *	be altered by the caller.  The caller may alter the contents of
	// *	these objects by using the set mechanisms.
	// *********************************************************************
	virtual int getVersion    ( short & version );
	virtual int getClientID   ( short & clientID );
	int getTransIndex         ( unsigned & transIndex );
	int getCancelTransIndex   ( unsigned & cancelTransIndex );
	int getLocalDataIndex     ( unsigned & localDataIndex );
	int getForeignDataIndex   ( unsigned & foreignDataIndex );
	int getOperationCode      ( unsigned & operationCode );
	int getCompletionCode     ( int & completionCode );
	int getDeviceList         ( char ** & deviceList, unsigned & deviceCount );
	int getMessage            ( char * & message );
	int getData               ( cdevData & data );
	int getContext            ( cdevData & context );
	int getTagMap             ( cdevData & tagMap );
	int get                   ( short    & clientID, 
				    unsigned & transIndex,
				    unsigned & cancelTransIndex,
				    unsigned & localDataIndex,
				    unsigned & foreignDataIndex,
				    unsigned & operationCode,
				    int      & completionCode,
				    unsigned & deviceCount,
				    char **  & deviceList,
				    char *   & message,
				    cdevData & data,
				    cdevData & context,
				    cdevData & tagMap);

	// *********************************************************************
	// * The has mechanisms:
	// *	This collection of functions allows the caller to determine if
	// *	certain components of the packet are present.
	// *********************************************************************
	int hasClientID         ( void ) { return map.value.clientIDSet; }
	int hasTransIndex       ( void ) { return map.value.transIndexSet; }
	int hasCancelTransIndex ( void ) { return map.value.cancelTransIndexSet; }
	int hasLocalDataIndex   ( void ) { return map.value.localDataIndexSet; }
	int hasForeignDataIndex ( void ) { return map.value.foreignDataIndexSet; }
	int hasOperationCode    ( void ) { return map.value.operationCodeSet; }
	int hasCompletionCode   ( void ) { return map.value.completionCodeSet; }
	int hasDeviceList       ( void ) { return map.value.deviceListSet; }
	int hasMessage          ( void ) { return map.value.messageSet; }
	int hasData             ( void ) { return map.value.dataSet; }
	int hasContext          ( void ) { return map.value.contextSet; }
	int hasTagMap           ( void ) { return map.value.tagMapSet; }
};


#endif /* CDEV_PACKET_BINARY_H_ */
