magic/utils/dqueue.c

261 lines
5.8 KiB
C

/*
* dqueue.c --
*
* Routines for double ended queues. See 'dqueue.h'.
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/dqueue.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include "utils/magic.h"
#include "utils/dqueue.h"
#include "utils/malloc.h"
/*
* ----------------------------------------------------------------------------
*
* DQInit --
*
* Initialize a new queue to have a certain capacity.
*
* Results:
* None.
*
* Side Effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
DQInit(q, capacity)
DQueue *q;
int capacity;
{
if (capacity < 1) capacity = 1;
q->dq_data = (ClientData *) mallocMagic((unsigned)((capacity+1) * sizeof (ClientData)));
q->dq_size = 0;
q->dq_maxSize = capacity;
q->dq_front = 0; /* next slot in front is loc 0 */
q->dq_rear = 1; /* next slot in rear is loc 1 */
}
/*
* ----------------------------------------------------------------------------
*
* DQFree --
*
* Free up a queue.
*
* Results:
* None.
*
* Side Effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
DQFree(q)
DQueue *q;
{
freeMagic((char *) q->dq_data);
}
/*
* ----------------------------------------------------------------------------
*
* DQPushFront & DQPushRear --
*
* Push a new element onto one end of the DQueue.
*
* Results:
* None.
*
* Side Effects:
* Puts an element in the queue.
*
* ----------------------------------------------------------------------------
*/
void
DQPushFront(q, elem)
DQueue *q;
ClientData elem;
{
if (q->dq_size == q->dq_maxSize) DQChangeSize(q, 2 * q->dq_maxSize);
q->dq_data[q->dq_front] = elem;
q->dq_front--;
if (q->dq_front < 0) q->dq_front = q->dq_maxSize;
q->dq_size++;
}
void
DQPushRear(q, elem)
DQueue *q;
ClientData elem;
{
if (q->dq_size == q->dq_maxSize) DQChangeSize(q, 2 * q->dq_maxSize);
q->dq_data[q->dq_rear] = elem;
q->dq_rear++;
if (q->dq_rear > q->dq_maxSize) q->dq_rear = 0;
q->dq_size++;
}
/*
* ----------------------------------------------------------------------------
*
* DQPopFront & DQPopRear --
*
* Pop an element from one end of the queue.
*
* Results:
* The element, or NULL if there is none.
*
* Side Effects:
* Removes the element from the queue.
*
* ----------------------------------------------------------------------------
*/
ClientData
DQPopFront(q)
DQueue *q;
{
if (q->dq_size == 0) return (ClientData) NULL;
q->dq_size--;
q->dq_front++;
if (q->dq_front > q->dq_maxSize) q->dq_front = 0;
return q->dq_data[q->dq_front];
}
ClientData
DQPopRear(q)
DQueue *q;
{
if (q->dq_size == 0) return (ClientData) NULL;
q->dq_size--;
q->dq_rear--;
if (q->dq_rear < 0) q->dq_rear = q->dq_maxSize;
return q->dq_data[q->dq_rear];
}
/*
* ----------------------------------------------------------------------------
*
* DQChangeSize --
*
* Change the size of a DQueue -- either increase or decrease.
*
* Results:
* None
*
* Side Effects:
* The DQueue changes size.
*
* ----------------------------------------------------------------------------
*/
void
DQChangeSize(q, newSize)
DQueue *q;
int newSize;
{
DQueue newq;
if (newSize < q->dq_size) newSize = q->dq_size;
DQInit(&newq, newSize);
DQCopy(&newq, q);
freeMagic((char *) q->dq_data);
q->dq_data = newq.dq_data;
q->dq_maxSize = newq.dq_maxSize;
q->dq_front = newq.dq_front;
q->dq_rear = newq.dq_rear;
}
/*
* ----------------------------------------------------------------------------
*
* DQCopy --
*
* Copy one DQueue into another.
*
* Results:
* None.
*
* Side Effects:
* Elements (ClientData pointers) are copied.
*
* ----------------------------------------------------------------------------
*/
void
DQCopy(dst, src)
DQueue *dst; /* The destination queue */
DQueue *src; /* The source queue */
{
int i;
dst->dq_size = 0;
i = src->dq_front;
while (dst->dq_size != src->dq_size) {
i = i + 1;
if (i > src->dq_maxSize) i = 0;
DQPushRear(dst, src->dq_data[i]);
}
}
/*
* ----------------------------------------------------------------------------
*
* Main --
*
* Test out this module.
*
* Results:
* None.
*
* Side Effects:
* Stuff on the screen.
*
* ----------------------------------------------------------------------------
*/
/****
void
main()
{
int i;
DQueue q;
DQInit(&q, 0);
for (i = 0; i < 10; i++) DQPushFront(&q, (ClientData) i);
while (!DQIsEmpty(&q)) printf("got %d\n", (int) DQPopRear(&q));
DQFree(&q);
printf("-------\n");
DQInit(&q, 0);
for (i = 0; i < 10; i++) DQPushFront(&q, (ClientData) i);
for (i = 0; i < 10000; i++) DQPushRear(&q, DQPopFront(&q));
for (i = 0; i < 10000; i++) DQPushFront(&q, DQPopRear(&q));
while (!DQIsEmpty(&q)) printf("got %d\n", (int) DQPopFront(&q));
}
****/