716 lines
11 KiB
C
716 lines
11 KiB
C
|
/******************************************************************
|
||
|
**
|
||
|
** QUEUE.C:
|
||
|
**
|
||
|
** ADT Queue Implementation
|
||
|
**
|
||
|
** This file is part of Apt Abstrct Data Types (ADT)
|
||
|
** Copyright (c) 1991 -- Apt Technologies
|
||
|
** All rights reserved
|
||
|
**
|
||
|
******************************************************************/
|
||
|
|
||
|
/* ---------- C Headers */
|
||
|
|
||
|
//#include "cheaders.h"
|
||
|
|
||
|
/* ---------- Headers */
|
||
|
|
||
|
#include "apt.h"
|
||
|
|
||
|
#include "allocate.h"
|
||
|
#include "pqueue.h"
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
/* ---------- Private Function Prototypes */
|
||
|
|
||
|
#ifdef __ANSI_C__
|
||
|
PRIVATE void QueueDisposeItem(QueueItem, DisposeFunction);
|
||
|
PRIVATE QueueItem QueueGetItem(Queue);
|
||
|
PRIVATE QueueItem QueueNewItem(void*, int);
|
||
|
PRIVATE void QueuePutItem(Queue, QueueItem);
|
||
|
PRIVATE QueueItem QueueRemoveItem(Queue, QueueItem);
|
||
|
PRIVATE int QueueCompareEqual(void *, void *);
|
||
|
#else
|
||
|
PRIVATE void QueueDisposeItem();
|
||
|
PRIVATE QueueItem QueueGetItem();
|
||
|
PRIVATE QueueItem QueueNewItem();
|
||
|
PRIVATE void QueuePutItem();
|
||
|
PRIVATE QueueItem QueueRemoveItem();
|
||
|
PRIVATE int QueueCompareEqual();
|
||
|
#endif
|
||
|
|
||
|
/* ---------- Functions */
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueApply
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueueApply(Queue q, ApplyFunction f)
|
||
|
#else
|
||
|
void QueueApply(q,f)
|
||
|
Queue q;
|
||
|
ApplyFunction f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
(*f)(item->element);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueApply1
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueueApply1(Queue q, void *p1, ApplyFunction1 f)
|
||
|
#else
|
||
|
void QueueApply1(q,p1,f)
|
||
|
Queue q;
|
||
|
void *p1;
|
||
|
ApplyFunction1 f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
(*f)(item->element,p1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueApply2
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueueApply2(Queue q, void *p1, void *p2, ApplyFunction2 f)
|
||
|
#else
|
||
|
void QueueApply2(q,p1,p2,f)
|
||
|
Queue q;
|
||
|
void *p1;
|
||
|
void *p2;
|
||
|
ApplyFunction2 f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
(*f)(item->element,p1,p2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueApply3
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueueApply3(Queue q, void *p1, void* p2, void *p3, ApplyFunction3 f)
|
||
|
#else
|
||
|
void QueueApply3(q,p1,p2,p3,f)
|
||
|
Queue q;
|
||
|
void *p1;
|
||
|
void *p2;
|
||
|
void *p3;
|
||
|
ApplyFunction3 f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
(*f)(item->element,p1,p2,p3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueCAR
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueCAR(Queue q)
|
||
|
#else
|
||
|
void *QueueCAR(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
if (q != NULL && q->head != NULL)
|
||
|
return QueueItemElement(q->head);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueCDR
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
Queue QueueCDR(Queue q)
|
||
|
#else
|
||
|
Queue QueueCDR(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
if (q != NULL && q->head != NULL) {
|
||
|
Queue new = QueueNew();
|
||
|
new->head = q->head->next;
|
||
|
new->tail = new->head != NULL ? q->tail : NULL;
|
||
|
new->size = q->size-1;
|
||
|
return new;
|
||
|
} else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueDispose
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueueDispose(Queue q, DisposeFunction f)
|
||
|
#else
|
||
|
void QueueDispose(q,f)
|
||
|
Queue q;
|
||
|
DisposeFunction f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
QueueItem next = NULL;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = next) {
|
||
|
next = item->next;
|
||
|
QueueDisposeItem(item,f);
|
||
|
}
|
||
|
free(q);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueDisposeItem
|
||
|
**
|
||
|
*/
|
||
|
PRIVATE
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueueDisposeItem(QueueItem item, DisposeFunction f)
|
||
|
#else
|
||
|
void QueueDisposeItem(item,f)
|
||
|
QueueItem item;
|
||
|
DisposeFunction f;
|
||
|
#endif
|
||
|
{
|
||
|
if (f) (*f)(item->element);
|
||
|
free(item);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueFind
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueFind(Queue q, void *element, ComparisonFunction f)
|
||
|
#else
|
||
|
void *QueueFind(q,element,f)
|
||
|
Queue q;
|
||
|
void *element;
|
||
|
ComparisonFunction f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
if ((*f)(element,item->element) == 0) break;
|
||
|
}
|
||
|
return (item != NULL ? item->element : NULL);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueFindAndRemove
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueFindAndRemove(Queue q, void *element,
|
||
|
ComparisonFunction f)
|
||
|
#else
|
||
|
void *QueueFindAndRemove(q, element, f)
|
||
|
Queue q;
|
||
|
void *element;
|
||
|
ComparisonFunction f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
if ((*f)(element,item->element) == 0) break;
|
||
|
}
|
||
|
item = QueueRemoveItem(q,item);
|
||
|
return (item != NULL ? item->element : NULL);
|
||
|
}
|
||
|
/*
|
||
|
**
|
||
|
** QueueFindAndRemoveType
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueFindAndRemoveType(Queue q, void *element,
|
||
|
ComparisonFunction f, int type)
|
||
|
#else
|
||
|
void *QueueFindAndRemoveType(q, element, f, type)
|
||
|
Queue q;
|
||
|
void *element;
|
||
|
ComparisonFunction f;
|
||
|
int type;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
if ((*f)(element,item->element) == 0 && item->type == type) break;
|
||
|
}
|
||
|
item = QueueRemoveItem(q,item);
|
||
|
return (item != NULL ? item->element : NULL);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueFindType
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueFindType(Queue q, int type)
|
||
|
#else
|
||
|
void *QueueFindType(q,type)
|
||
|
Queue q;
|
||
|
int type;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
if (item->type == type) break;
|
||
|
}
|
||
|
return (item != NULL ? item->element : NULL);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueFindTypeAndRemove
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueFindTypeAndRemove(Queue q, int type)
|
||
|
#else
|
||
|
void *QueueFindTypeAndRemove(q,type)
|
||
|
Queue q;
|
||
|
int type;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
for (item = q->head; item != NULL; item = item->next) {
|
||
|
if (item->type == type) break;
|
||
|
}
|
||
|
return (QueueRemoveItem(q,item));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueGet
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueGet(Queue q)
|
||
|
#else
|
||
|
void *QueueGet(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
void *element;
|
||
|
QueueItem item;
|
||
|
|
||
|
item = QueueGetItem(q);
|
||
|
if (item) {
|
||
|
element = item->element;
|
||
|
QueueDisposeItem(item,NULL);
|
||
|
}
|
||
|
else element = NULL;
|
||
|
return (element);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueGetItem
|
||
|
**
|
||
|
*/
|
||
|
PRIVATE
|
||
|
#ifdef __ANSI_C__
|
||
|
QueueItem QueueGetItem(Queue q)
|
||
|
#else
|
||
|
QueueItem QueueGetItem(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
if (q->head) {
|
||
|
item = q->head;
|
||
|
q->head = q->head->next;
|
||
|
q->size--;
|
||
|
}
|
||
|
else item = NULL;
|
||
|
return (item);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueHead
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
QueueItem QueueHead(Queue q)
|
||
|
#else
|
||
|
QueueItem QueueHead(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
return q != NULL ? q->head : NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueItemElement
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueItemElement(QueueItem item)
|
||
|
#else
|
||
|
void *QueueItemElement(item)
|
||
|
QueueItem item;
|
||
|
#endif
|
||
|
{
|
||
|
return (item->element);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueItemType
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
int QueueItemType(QueueItem item)
|
||
|
#else
|
||
|
int QueueItemType(item)
|
||
|
QueueItem item;
|
||
|
#endif
|
||
|
{
|
||
|
return (item->type);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueLook
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void *QueueLook(Queue q)
|
||
|
#else
|
||
|
void *QueueLook(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
item = q->head;
|
||
|
return (item != NULL ? item->element : NULL);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueNew
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
Queue QueueNew(void)
|
||
|
#else
|
||
|
Queue QueueNew()
|
||
|
#endif
|
||
|
{
|
||
|
Queue q;
|
||
|
|
||
|
q = ((Queue)Allocate(sizeof(_Queue)));
|
||
|
if (q) {
|
||
|
q->head = q->tail = NULL;
|
||
|
q->size = 0;
|
||
|
}
|
||
|
return (q);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueNewItem
|
||
|
**
|
||
|
*/
|
||
|
PRIVATE
|
||
|
#ifdef __ANSI_C__
|
||
|
QueueItem QueueNewItem(void *element, int type)
|
||
|
#else
|
||
|
QueueItem QueueNewItem(element,type)
|
||
|
void *element;
|
||
|
int type;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
item = ((QueueItem)Allocate(sizeof(_QueueItem)));
|
||
|
if (item) {
|
||
|
item->element = element;
|
||
|
item->type = type;
|
||
|
item->next = NULL;
|
||
|
}
|
||
|
return (item);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueNext
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
QueueItem QueueNext(QueueItem item)
|
||
|
#else
|
||
|
QueueItem QueueNext(item)
|
||
|
QueueItem item;
|
||
|
#endif
|
||
|
{
|
||
|
return item != NULL ? item->next : NULL;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueuePut
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueuePut(Queue q, void *element, int type)
|
||
|
#else
|
||
|
void QueuePut(q,element,type)
|
||
|
Queue q;
|
||
|
void *element;
|
||
|
int type;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
|
||
|
item = QueueNewItem(element,type);
|
||
|
QueuePutItem(q,item);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueuePutItem
|
||
|
**
|
||
|
*/
|
||
|
PRIVATE
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueuePutItem(Queue q, QueueItem item)
|
||
|
#else
|
||
|
void QueuePutItem(q,item)
|
||
|
Queue q;
|
||
|
QueueItem item;
|
||
|
#endif
|
||
|
{
|
||
|
if (q->head == NULL) {
|
||
|
q->head = q->tail = item;
|
||
|
} else {
|
||
|
q->tail->next = item;
|
||
|
q->tail = q->tail->next;
|
||
|
}
|
||
|
q->size++;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueuePutOnPriority
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
void QueuePutOnPriority(Queue q, void *element, int type,
|
||
|
ComparisonFunction f)
|
||
|
#else
|
||
|
void QueuePutOnPriority(q,element,type,f)
|
||
|
Queue q;
|
||
|
void *element;
|
||
|
int type;
|
||
|
ComparisonFunction f;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
item = QueueNewItem(element,type);
|
||
|
//fprintf(stderr,"searching for location using %p.\n",f);
|
||
|
if (f == NULL){
|
||
|
//fprintf(stderr,"comparing function is null %f \n",f);
|
||
|
exit(1);
|
||
|
QueuePutItem(q,item);
|
||
|
|
||
|
}else {
|
||
|
if (q->head == NULL) QueuePutItem(q,item);
|
||
|
else {
|
||
|
QueueItem p, lastp = NULL;
|
||
|
for (p = q->head; p != NULL; p = p->next) {
|
||
|
int cval =(*f)(element,p->element);
|
||
|
if (cval<0){
|
||
|
// fprintf(stderr,"%i <=> %i == %i\n",*((int *) element),*((int *)(p->element)),
|
||
|
// cval);
|
||
|
break;
|
||
|
}
|
||
|
lastp = p;
|
||
|
}
|
||
|
if (p == q->head) {
|
||
|
item->next = q->head;
|
||
|
q->head = item;
|
||
|
} else if (p == NULL) {
|
||
|
q->tail->next = item;
|
||
|
q->tail = q->tail->next;
|
||
|
} else {
|
||
|
item->next = p;
|
||
|
lastp->next = item;
|
||
|
}
|
||
|
q->size++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueRemoveItem
|
||
|
**
|
||
|
*/
|
||
|
PRIVATE
|
||
|
#ifdef __ANSI_C__
|
||
|
QueueItem QueueRemoveItem(Queue q, QueueItem item)
|
||
|
#else
|
||
|
QueueItem QueueRemoveItem(q,item)
|
||
|
Queue q;
|
||
|
QueueItem item;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem this, prev = NULL;
|
||
|
|
||
|
if (q == NULL) return (NULL);
|
||
|
if (item == NULL) return (NULL);
|
||
|
this = q->head;
|
||
|
while (this && this != item) {
|
||
|
prev = this; this = this->next;
|
||
|
}
|
||
|
if (this == NULL) return (NULL);
|
||
|
if (this == q->head) q->head = item->next;
|
||
|
if (this == q->tail) q->tail = prev;
|
||
|
if (prev) prev->next = this->next;
|
||
|
q->size--;
|
||
|
return (item);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueSeek
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
QueueItem QueueSeek(Queue q, int position)
|
||
|
#else
|
||
|
QueueItem QueueSeek(q,position)
|
||
|
Queue q;
|
||
|
int position;
|
||
|
#endif
|
||
|
{
|
||
|
QueueItem item;
|
||
|
#if 0
|
||
|
/* Allow single-level negative addressing of queue items */
|
||
|
if (position <= 0)
|
||
|
position += QueueSize(q);
|
||
|
#endif
|
||
|
/* Seeks which fail will result in NULL, not error conditions */
|
||
|
if (position <= 0 || position > QueueSize(q))
|
||
|
return NULL;
|
||
|
item = QueueHead(q);
|
||
|
while (--position > 0)
|
||
|
item = QueueNext(item);
|
||
|
return item;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueSize
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
int QueueSize(Queue q)
|
||
|
#else
|
||
|
int QueueSize(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
return q != NULL ? q->size : 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
**
|
||
|
** QueueTail
|
||
|
**
|
||
|
*/
|
||
|
PUBLIC
|
||
|
#ifdef __ANSI_C__
|
||
|
QueueItem QueueTail(Queue q)
|
||
|
#else
|
||
|
QueueItem QueueTail(q)
|
||
|
Queue q;
|
||
|
#endif
|
||
|
{
|
||
|
return q != NULL ? q->tail : NULL;
|
||
|
}
|
||
|
|
||
|
PRIVATE
|
||
|
#ifdef __ANSI_C__
|
||
|
int QueueCompareEqual(void *x, void *y)
|
||
|
#else
|
||
|
int QueueCompareEqual(x,y)
|
||
|
void *x, *y;
|
||
|
#endif
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|