/*---------------------------------------------------------- * HTBLA-Leonding / Class: 2IHIF * --------------------------------------------------------- * Exercise Number: S03 * Title: Queue implementation * Author: Marc Tismonar * ---------------------------------------------------------- * Description: * Implementation of a queue based on an advanced singly linked list. * ---------------------------------------------------------- */ /* Implementation notes: 1) The 'QueueData' struct SHALL encapsulate the underlying list to decouple queue and queue interfaces. No further members are required. 2) Queue allocation: Use functions `mem_alloc(…)` and `mem_free(…)` declared in `allocator.h`. DO NOT use `malloc(…)` and `free(…)` directly as unit tests will fail. 3) Avoid code duplication wherever (reasonably) possible. The implemenation of each function mostly delegates to the corresponding queue function (one-liners). Implement the combined functionality of 'dequeue' and 'peek' as a single private function which is used by 'dequeue' and 'peek'. */ /* includes */ #include #include "queue.h" #include "advanced_singly_linked_list.h" #include "allocator.h" /** The implementation of queue data */ struct IntQueueData { IntList list; }; /* ===================================================================== */ /* private queue functions */ /* ===================================================================== */ /** * Obtains ('creates') and provides a 'new' queue instance. * Any queue obtained via this function MUST be released using * function `release_queue()`. * * Note: This function does not make any assumptions * about how queue components, esp. nodes, are allocated. * * @return IntQueue The queue instance or 0, if no queue could by instantiated. */ IntQueue queue_obtain() { IntQueue queue = (IntQueue)alloc_mem(sizeof(struct IntQueueData)); if (queue != 0) { queue->list = list_obtain(); } return queue; } /** * Releases a queue that was obtained earlier via function `obtain_queue`. * Released queues MUST NOT be used anymore. * * Note: The implementation of this function does not make any assumptions * about the allocation method of queue elements, but MUST match the implementation * of function `obtain_queue` as its inverse function. * * @param p_queue The pointer to the queue to release. The value of the pointer * is set to 0, if the queue was successfully released, otherwise it is left untouched. */ IntQueue queue_release(IntQueue* p_queue) { if (p_queue == 0 || *p_queue == 0) { return 0; } IntQueue queue = *p_queue; list_release(&queue->list); free_mem(queue); *p_queue = 0; return queue; } /** * Determines whether or not the given queue is valid. * * @param queue The queue to evaluate. * @return `True` if the queue is valid, false otherwise. */ bool queue_is_valid(IntQueue queue) { return queue != 0 && queue->list != 0; } /** * Determines whether or not the queue contains at least one item. * * @param queue The queue to evaluate. * @return `False` if the queue contains one or more items, `true` otherwise. */ bool queue_is_empty(IntQueue queue) { return !queue_is_valid(queue) || list_is_empty(queue->list); } /** * Provides the number of values stored in the queue. * * @param queue The queue to evaluate. * @return The number of values the queue contains. */ int queue_get_size(IntQueue queue) { if (!queue_is_valid(queue)) { return 0; } return list_get_size(queue->list); } /** * Clears the given queue by removing all values from the queue. * * @param queue The queue to clear. */ void queue_clear(IntQueue queue) { if (!queue_is_valid(queue)) { return; } list_clear(queue->list); } /** * Inserts the given value to the queue (as new tail). * * @param queue The queue to which the value shall be appended. * @param value The value to append to the queue. */ void queue_enqueue(IntQueue queue, int value) { if (!queue_is_valid(queue)) { return; } list_insert(queue->list, value); } /** * Provides the value that 'dequeue' would provided but WITHOUT removing * this value from the queue. * * @param queue The queue from which the value shall be peeked. * @return The next value or 0, if the queue is empty. */ int queue_peek(IntQueue queue) { if (!queue_is_valid(queue)) { return 0; } return list_get_at(queue->list, 0); } /** * Provides AND removes the next value from the queue. * * @param queue The queue from which the value shall be removed and returned. * @return The value or 0, if the queue is empty. */ int queue_dequeue(IntQueue queue) { if (!queue_is_valid(queue)) { return 0; } int value = list_get_at(queue->list, 0); list_remove_at(queue->list, 0); return value; }