#ifndef _CDEV_STREAM_QUEUE_H_
#define _CDEV_STREAM_QUEUE_H_

#include "cdevStreamNode.h"

// *****************************************************************************
// * class cdevSimpleStreamNode :
// *	This is a simple implementation class of the cdevStreamNode.  It will 
// *	be used if the developer does not provide his own implementation class.
// *****************************************************************************
class CDEV_REACTOR_API cdevSimpleStreamNode : public cdevStreamNode
{
protected:
	char * buf;
	size_t len;
	
public:
	cdevSimpleStreamNode ( char * buffer=NULL, size_t size=0);		
	~cdevSimpleStreamNode ( void );

	size_t getLen (void) const;
	void   setLen (size_t size);
	char * getBuf (void) const;
	void   setBuf (char * buffer, size_t size);
};


// *****************************************************************************
// * class cdevNodeFactory :
// *	This class will generate a user defined instance of a cdevStreamNode
// *	sub-class.  This class is used within the cdevBufferedSocket to
// *	convert incoming binary packets into a user defined structure.
// *****************************************************************************
class CDEV_REACTOR_API cdevNodeFactory 
{
public:
	virtual ~cdevNodeFactory ( void );
	
	virtual cdevStreamNode * newNode ( ssize_t size ) = 0;
};



// *****************************************************************************
// * class cdevStreamQueue :
// *	This is a class that will store the data items that are being enqueued
// *	by the cdevBufferedSocket.
// *****************************************************************************
class CDEV_REACTOR_API cdevStreamQueue
{
private:
	cdevStreamNode * head;
	cdevStreamNode * tail;
	int              deleteFlag;
	size_t           nEntries;
	size_t           totalLen;
	
public:
	cdevStreamQueue ( int deleteNodesFlag = 1 ) 
		: head(NULL), tail(NULL), deleteFlag(deleteNodesFlag), 
		  nEntries(0), totalLen(0)
		{
		}

	~cdevStreamQueue ( void )
		{
		if(deleteFlag) while(!isEmpty()) delete dequeue();
		}	
	
	void enqueue( cdevStreamQueue & queue )
		{
		head           = queue.head;
		tail           = queue.tail;
		nEntries       = queue.nEntries;
		totalLen       = queue.totalLen;
		queue.head     = NULL;
		queue.tail     = NULL;
		queue.nEntries = 0;
		queue.totalLen = 0;
		}
		
	void enqueue ( cdevStreamNode * node )
		{
		if(node)
			{
			if(tail!=NULL) tail->setNext(node);
			else head = node;
			tail      = node;
			totalLen+=(node->getLen()+sizeof(node->getLen()));
			nEntries++;
			}
		}

	cdevStreamNode * dequeue ( void )
		{
		cdevStreamNode * node = NULL;
		if(head!=NULL)
			{
			node = head;
			head = node->getNext();
			node->setNext(NULL);
			if(head==NULL) tail = NULL;
			totalLen-=(node->getLen()+sizeof(node->getLen()));
			nEntries--;
			}
		return node;
		}
	
	cdevStreamNode * peek ( void )
		{
		return head;
		}
		
	void poke ( cdevStreamNode * node )
		{
		node->setNext(head);
		head = node;
		if(tail==NULL) tail = head;
		}

	int    isEmpty       ( void ) const { return head==NULL?1:0; }
	size_t getCount      ( void ) const { return nEntries; }
	size_t getSize       ( void ) const { return totalLen; }
};

#endif /* _CDEV_STREAM_QUEUE_H */
