/*			QUEUE.C
 *
 */

#include "queue.h"
#include <ctype.h>
/*#define testing*/
/*#define debug*/

#ifdef testing

#include <gcl.h>

int qtab[10]= {0,0,0,0,0,0,0,0,0,0};

main()
{
	char *in;
	int qn;
	char *d;

	while(!GCLEOF) {

		in=gcl("\n\rQUEUE test ... Enter \"#[d] <data>\" >");

		if(!isdigit(*in))
			printf("QUEUE test ... error first must come the queue number\n");
		else {
			qn=*in-'0';
			switch (toupper(*(in+1))) {
			 case 'D' :
				printf("QUEUE test ... Removing queue %d\n",qn);
				if(qtab[qn])
					quedel(qtab[qn]);
				qtab[qn]=0;
				break;
			 case 'R' :
				dequeue(qtab[qn],&d,0);
				printf("DATA > <%s>\n",d);
				free(d);
				break;
			 default :
				if (!qtab[qn]) {
					printf("QUEUE test ... Initializing new queue\n");
					qtab[qn]=queinit();
#ifdef debug
					printf("MAIN 1>que address[%oo]\n",qtab[qn]);
#endif
				}
				printf("elements >[%dd]\n",queue(qtab[qn],in+2,strlen(in+2)+1));
			}
		}
	}
}

#endif



/*			QUEUE
 *	Put an element into a queue
 * Returns number of elements in the queue
 * or -1 for run out of memory
 */

queue(hdrptr,datptr,datlen)
 quehdr *hdrptr;				/* Pointer to queue header */
 byte *datptr;					/* Pointer to data */
 unsigned datlen;				/* Size of data (bytes) */
{
	quepkt *newpkt;				/* Pointer to new packet */
	quepkt *oldend;				/* Pointer to what was the last */

	if(!(newpkt=malloc(sizeof(quepkt))))	/* Allocate memory for packet */
		return(-1);
	newpkt->datsiz=datlen;			/* Set size of data packet */

	if(!(newpkt->data=malloc(datlen))) {
		free(newpkt);
		return(-1);
	}
	copy(newpkt->data,datptr,datlen);	/* Put data into packet */
#ifdef debug
	printf("queue 1>newpkt[%oo] datsiz[%oo] data[%oo] next[%oo]\n",
	newpkt,newpkt->datsiz,newpkt->data,newpkt->next);
#endif

	oldend=hdrptr->tail;			/* Point to last packet */
	hdrptr->tail=newpkt;			/* Set new last packet */
	if(hdrptr->eltcnt)			/* If there was a last packet */
		oldend->next=newpkt;		/* Link it into the list */
	else
		hdrptr->head=newpkt;		/* else link in the head */
#ifdef debug
	printf("queue 2>hdrptr[%oo] head[%oo] tail[%oo] eltcnt[%oo]\n",
	hdrptr,hdrptr->head,hdrptr->tail,hdrptr->eltcnt);
#endif

	return(++(hdrptr->eltcnt));		/* Return count */
}

/*			DEQUEUE
 *	Get an element from a que
 * returns the size of the element
 */

int dequeue(hdrptr,buf,size)
quehdr *hdrptr;					/* Which queue to get from */
char *buf;					/* Pointer to buffer to fill */
int size;					/* Maximum # bytes to put */
{
	quepkt *deqpkt;				/* Packet to de-queue */

	/* Make sure we have packets to give called */
	if(hdrptr->eltcnt) {

		deqpkt=hdrptr->head;			/* Point de-queue packet */

		/* If the caller passes 0 down for size, then he just wants a
		   pointer to the packet otherwise he wants the packet copied
		   into the buffer he's specified */
		if(size) {
			/* copy the buffer to where the caller want's it */
			copy(buf,&(deqpkt->data),(size<deqpkt->datsiz)?size:deqpkt->datsiz);
			free(deqpkt->data);
		} else {
			*((char **)buf)=deqpkt->data;
		}

		/* Un-link the data packet */
		hdrptr->head=deqpkt->next;

		/* Free up the memory used by the packet */
		free(deqpkt);

		/* Decrement packet counter */
		(hdrptr->eltcnt)--;

		/* Return size of packet */
		return(deqpkt->datsiz);
	} else {
		return(-1);
	}
}


/*			QUEDEL
 * Delete a queue
 *	Returns nothing usefull
 */

quedel(quep)
quehdr *quep;
{
	quepkt *eltp;		/* Pointer to individual queue packets */
	int cnt;		/* count of elements to go */

#ifdef  debug
	printf("quedel 1>quep[%oo] head[%oo] tail[%oo] eltcnt[%oo]\n"
	,quep,quep->head,quep->tail,quep->eltcnt);
#endif
	eltp=quep->head;
	for(cnt=quep->eltcnt ; (cnt--) ; eltp=eltp->next) {
#ifdef debug
	printf("quedel 2>cnt[%dd] eltp[%oo] next[%oo] datsiz[%dd] data[%oo]\n"
	,cnt,eltp,eltp->next,eltp->datsiz,eltp->data);
#endif
		free(eltp->data);
		free(eltp);
	}

	return(free(quep));
}
			

/*			QUEINIT
 *	Initialize a queue
 * Returns pointer to queue header
 * 0 for error
 */

queinit()
{
	quehdr *hp;

	hp=malloc(sizeof(quehdr));
	if(hp)
		hp->eltcnt=0;
	return(hp);
}
