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