/* ---------------------CIRCULAR ARRAY QUEUE IMPLEMTATION------------------- */ /* * VERSION * Jun 17th 2026 * * API * queue q_new(size_t n); * int q_is_empty(queue *q); * int q_is_full(queue *q); * int q_enqueue(queue *q, void *item); * void *q_dequeue(queue *q); * void *q_peek(queue *q); * * TODO * q_grow: grow the size * q_shrink: shrink the size * q_cap: set the size to current sizeshrink the size * q_length: get current length * */ /* ---------------------CIRCULAR ARRAY QUEUE IMPLEMTATION------------------- */ #ifndef QUEUE_H_ #define QUEUE_H_ /* * Goes before declarations and definitions of functions */ #ifndef QDEF # define QDEF #endif /* QDEF */ /* * Goes before definitions of functions that can be inlined: * q_is_empty q_is_full */ #ifndef QINLINE # define QINLINE #endif /* QINLINE */ #include #define Q_NULL NULL #define Q_EMPTY_IDX -1 #define Q_DONE 0 /* non-errorous operation guaranteed to be 0 */ #define Q_FULL 1 typedef struct { ssize_t head; ssize_t tail; size_t size; void **items; } queue; QDEF queue q_new(size_t n); QDEF int q_is_empty(queue *q); QDEF int q_is_full(queue *q); QDEF int q_enqueue(queue *q, void *item); QDEF void *q_dequeue(queue *q); QDEF void *q_peek(queue *q); #if defined(QUEUE_DEBUG_) || \ defined(QUEUE_AGGRESIVE_DEBUG_) # include QDEF void q_dump(FILE *f, queue *q); #endif /* QUEUE_DEBUG_ */ #endif /* QUEUE_H_ */ /* -------------------------------------------------------------------------- */ #define QUEUE_IMPLEMENTATION #ifdef QUEUE_IMPLEMENTATION #include /* for malloc() */ #include /* for memset() */ #define Q_NEXT_TAIL_IDX(q) (q->tail + 1) % (long) q->size #define Q_NEXT_HEAD_IDX(q) (q->head + 1) % (long) q->size /* * create a new queue with size of N */ queue q_new(size_t n) { queue q = {0}; void **items = malloc(n * sizeof(void *)); memset(items, 0, n * sizeof(void *)); q.head = q.tail = Q_EMPTY_IDX; q.size = n; q.items = items; return q; } /* * check if Q is empty */ QINLINE QDEF int q_is_empty(queue *q) { return q->head == Q_EMPTY_IDX; } /* * check if Q is full */ QINLINE QDEF int q_is_full(queue *q) { return Q_NEXT_TAIL_IDX(q) == q->head; } /* * enqueue ITEM to q * * RETURNS Q_FULL if q is full * RETURNS Q_DONE if successful */ QDEF int q_enqueue(queue *q, void *item) { ssize_t next_tail; #if defined(QUEUE_AGGRESIVE_DEBUG_) fprintf(stdout, "q_enqueue: "); q_dump(stdout, q); #endif /* QUEUE_AGGRESIVE_DEBUG_ */ next_tail = Q_NEXT_TAIL_IDX(q); if (next_tail == q->head) return Q_FULL; if (q->head == Q_EMPTY_IDX) q->head = 0; q->tail = next_tail; (q->items)[next_tail] = item; #if defined(QUEUE_AGGRESIVE_DEBUG_) q_dump(stdout, q); #endif /* QUEUE_AGGRESIVE_DEBUG_ */ return Q_DONE; } QDEF void *q_dequeue(queue *q) { void *item; #if defined(QUEUE_AGGRESIVE_DEBUG_) fprintf(stdout, "q_dequeue: "); q_dump(stdout, q); #endif /* QUEUE_AGGRESIVE_DEBUG_ */ if (q->head == Q_EMPTY_IDX) return Q_NULL; item = (q->items)[q->head]; if (q->head == q->tail) q->head = q->tail = Q_EMPTY_IDX; else q->head = Q_NEXT_HEAD_IDX(q); #if defined(QUEUE_AGGRESIVE_DEBUG_) q_dump(stdout, q); #endif /* QUEUE_AGGRESIVE_DEBUG_ */ return item; } QDEF void *q_peek(queue *q) { if (q_is_empty(q)) return Q_NULL; return (q->items)[q->head]; } #if defined(QUEUE_DEBUG_) QDEF void q_dump(FILE *f, queue *q) { ssize_t i; fprintf(f, "QUEUE F%ld R%ld S%lu\n", q->head, q->head, q->size); for (i = 0; i < (long) q->size; i++) { fprintf(f, " %ld: %p %s%s%s\n", i, (void *) (q->items)[i], q->head == i || q->tail == i ? "<-" : "", q->head == i ? "F" : "", q->tail == i ? "R" : "" ); } fflush(f); } #endif /* QUEUE_DEBUG_ */ #endif /* QUEUE_IMPLEMENTATION */