Files
sermon/src/queue.h

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 */