/* QUEUE.C		Integer and character queue abstractions

	(C) 1982 Perfect Software, Inc.

	01/26/82	Version 1.00 by Barry A. Dobyns

These routines implement FIFO queues of 8- or 16- bit objects.  */

struct queue {
	int *head,*tail,*top,*bottom,space;
};

/*  Initialization routine (must be called before any operation done
	on the queue) */

IQInit(queue_p,size)
struct queue *queue_p;
int size;
{
	queue_p->head = queue_p->tail = queue_p->top = &(queue_p->space);
	queue_p->bottom = queue_p->top +size -1;
}

/* Routine to grab something off the head of a queue
Does no error checking!  Be careful of underflow! */

IQGrab(queue_p)
struct queue *queue_p;
{
	return ((queue_p->head >= queue_p->bottom) ?
	*(queue_p->head = queue_p->top) :
	*++(queue_p->head));
}

/* Routine to shove something onto the tail of a queue
   Does no error checking!  Be careful of overflow! */

IQShove(x,queue_p)
struct queue *queue_p;
int x;
{
	*((queue_p->tail >= queue_p->bottom) ?
	(queue_p->tail = queue_p->top) :
	++(queue_p->tail)) = x;
}

/* Emptiness predicate */

IQEmpty(queue_p)
struct queue *queue_p;
{
	return (queue_p->head == queue_p->tail);
}

/*fullth predicate */

IQFull(queue_p)
struct queue *queue_p;
{
	return((queue_p->tail+1 == queue_p->head) ||
	    (queue_p->tail == queue_p->bottom &&
	    queue_p->head == queue_p->top));
}

/* Peek at head of queue without disturbing it */

IQPeek(queue_p)
struct queue *queue_p;
{
	return ( (queue_p->head == queue_p->bottom)  ?
	*queue_p->top  :
	*(queue_p->head + 1)  );
}


/* The same routines, only set up for characters instead of integers */

struct cqueue {
	char *chead,*ctail,*ctop,*cbottom,cspace;
};

/*  Initialization routine (must be called before any operation done
	on the queue) */

CQInit(queue_p,size)
struct cqueue *queue_p;
int size;
{
	queue_p->chead = queue_p->ctail = queue_p->ctop = &(queue_p->cspace);
	queue_p->cbottom = queue_p->ctop +size -1;
}

/* Routine to grab something off the head of a queue
Does no error checking!  Be careful of underflow! */

CQGrab(queue_p)
struct cqueue *queue_p;
{
	return ((queue_p->chead >= queue_p->cbottom) ?
	*(queue_p->chead = queue_p->ctop) :
	*++(queue_p->chead));
}

/* Routine to shove something onto the tail of a queue
   Does no error checking!  Be careful of overflow! */

CQShove(x,queue_p)
struct cqueue *queue_p;
int x;
{
	*((queue_p->ctail >= queue_p->cbottom) ?
	(queue_p->ctail = queue_p->ctop) :
	++(queue_p->ctail)) = x;
}

/* Emptiness predicate */

CQEmpty(queue_p)
struct cqueue *queue_p;
{
	return (queue_p->chead == queue_p->ctail);
}

/*fullth predicate */

CQFull(queue_p)
struct cqueue *queue_p;
{
	return((queue_p->ctail+1 == queue_p->chead) ||
	    (queue_p->ctail == queue_p->cbottom &&
	    queue_p->chead == queue_p->ctop));
}

/* Peek at head of queue without disturbing it */

CQPeek(queue_p)
struct cqueue *queue_p;
{
	return ( (queue_p->chead == queue_p->cbottom)  ?
	*queue_p->ctop  :
	queue_p->chead[1]  );
}


/* End of QUEUE.C  --  queue abstractions */
