108 lines
2.9 KiB
C
108 lines
2.9 KiB
C
/***************************************************************************
|
|
* queue.h - macros for defining a double-ended queue
|
|
*
|
|
* Copyright (C) 2015 by David A. Baer, All Rights Reserved
|
|
*
|
|
* Description:
|
|
*
|
|
* These macros are designed to make it easier to process input whose
|
|
* length is unknown before it terminates (e.g. a series of numbers).
|
|
* The APPEND_QUEUE macro adds a new element to the list. The
|
|
* QUEUE_LENGTH macro provides the current length of the queue. The
|
|
* QUEUE_TO_ARRAY macro can convert the queue into a more compact
|
|
* array.
|
|
*
|
|
* Usage:
|
|
*
|
|
* DEFINE_QUEUE(MyType, QueueOfMyType);
|
|
* NEW_QUEUE(QueueOfMyType, myq);
|
|
* APPEND_QUEUE(QueueOfMyType, myq, VALUE1);
|
|
* APPEND_QUEUE(QueueOfMyType, myq, VALUE2);
|
|
* ...
|
|
* FOREACH_QUEUE(QueueOfMyType, myq, iterator) {
|
|
* (some action)
|
|
* }
|
|
* FOREACH_QUEUE_END <--- NOTE: THIS IS MANDATORY
|
|
* len = QUEUE_LENGTH(myq);
|
|
* QUEUE_TO_ARRAY(QueueOfMyType, myq, MyType, targetptr);
|
|
*
|
|
*
|
|
*/
|
|
#ifndef _QUEUE_H
|
|
#define _QUEUE_H
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#define DEFINE_QUEUE(T, N) \
|
|
struct _##N##Node { \
|
|
T data; \
|
|
struct _##N##Node* next; \
|
|
};\
|
|
typedef struct { \
|
|
int length; \
|
|
struct _##N##Node *head, *tail; \
|
|
} N
|
|
|
|
#define NEW_QUEUE(T, N) \
|
|
T N = (T) { .length = 0, .head = NULL, .tail = NULL }
|
|
|
|
/* WARNING: this is probably not what you want -- see DESTROY_QUEUE below */
|
|
#define REINIT_QUEUE(N) { \
|
|
(N).length = 0; \
|
|
(N).head = NULL; \
|
|
(N).tail = NULL; \
|
|
}
|
|
|
|
#define APPEND_QUEUE(T, Q, E) { \
|
|
struct _##T##Node* n = (struct _##T##Node*)malloc(sizeof(struct _##T##Node)); \
|
|
if (!n) { perror ("Could not allocate space for new queue element."); exit(1); } \
|
|
n->data = E; \
|
|
n->next = NULL; \
|
|
if ((Q).head == NULL) (Q).head = n; \
|
|
if ((Q).tail != NULL) (Q).tail->next = n; \
|
|
(Q).tail = n; \
|
|
(Q).length++; \
|
|
}
|
|
|
|
#define QUEUE_LENGTH(Q) (Q).length
|
|
|
|
#define FOREACH_QUEUE(T, Q, N) { \
|
|
struct _##T##Node* N = NULL; \
|
|
for (N = (Q).head; N != NULL; N = (N)->next)
|
|
|
|
#define FOREACH_QUEUE_END }
|
|
|
|
#define DESTROY_QUEUE(T, Q) { \
|
|
struct _##T##Node* ptr = (Q).head; \
|
|
while (ptr != NULL) { \
|
|
struct _##T##Node* temp = ptr->next; \
|
|
free(ptr); \
|
|
ptr = temp; \
|
|
} \
|
|
(Q).head = (Q).tail = NULL; \
|
|
(Q).length = 0; \
|
|
}
|
|
|
|
#define DESTROY_QUEUE_FUNC(T, Q, F) { \
|
|
struct _##T##Node* ptr = (Q).head; \
|
|
while (ptr != NULL) { \
|
|
struct _##T##Node* temp = ptr->next; \
|
|
F(ptr->data); \
|
|
free(ptr); \
|
|
ptr = temp; \
|
|
} \
|
|
(Q).head = (Q).tail = NULL; \
|
|
(Q).length = 0; \
|
|
}
|
|
|
|
#define QUEUE_TO_ARRAY(QT, Q, T, DST) { \
|
|
int i = 0; \
|
|
(DST) = (T*)calloc((Q).length,sizeof(T)); \
|
|
if (!(DST)) { perror("Could not allocate space for array."); exit(1); } \
|
|
FOREACH_QUEUE(QT, Q, ptr) \
|
|
(DST)[i++] = ptr->data; \
|
|
FOREACH_QUEUE_END; \
|
|
}
|
|
|
|
#endif /* !def _QUEUE_H */
|