#include #include #include #include "request_queue.h" typedef struct _rqueue_node { request data; struct _rqueue_node *next; struct _rqueue_node *prev; } rqueue_node; struct _rqueue { int size; int max; rqueue_node *head; rqueue_node *tail; }; rqueue *rqueue_create(int max) { rqueue *q = malloc(sizeof(rqueue)); if (q != NULL) { // initialize size and max q->size = 0; q->max = max; // create two dummy nodes for head and tail (these dummy nodes // contain no data; always having a head and tail eliminates // special cases from add and remove) q->head = malloc(sizeof(rqueue_node)); q->tail = malloc(sizeof(rqueue_node)); // make sure malloc succeeded if (q->head == NULL || q->tail == NULL) { free(q->head); free(q->tail); free(q); return NULL; } // link dummy head and tail together q->head->next = q->tail; q->head->prev = NULL; q->tail->prev = q->head; q->tail->next = NULL; // NULL out data in dummy head and tail (so they don't need // special treatment in destroy) q->head->data.user = NULL; q->head->data.position = NULL; q->tail->data.user = NULL; q->tail->data.position = NULL; } return q; } void rqueue_destroy(rqueue *q) { if (q != NULL) { // iterate through all nodes still remaining rqueue_node *curr = q->head; while (curr != NULL) { // free data in those nodes free(curr->data.user); free(curr->data.position); // remember a pointer to the next node rqueue_node *next = curr->next; // free the current node free(curr); // go to the next node curr = next; } // zero out the queue to make it more obviously wrong when // someone tries to use a queue that has just been destroyed q->size = 0; q->head = NULL; q->tail = NULL; // free the queue free(q); } } int rqueue_size(const rqueue *q) { if (q != NULL) { return q->size; } else { return 0; } } bool rqueue_add(rqueue *q, const request *r) { if (q == NULL || q->size == q->max || r == NULL || r->user == NULL || r->position == NULL) { return false; } else { // make new node rqueue_node *node = malloc(sizeof(rqueue_node)); // copy data into new node (with error checking on malloc) char *copy_user = malloc(sizeof(char) * (strlen(r->user) + 1)); char *copy_pos = malloc(sizeof(char) * (strlen(r->position) + 1)); if (node == NULL || copy_user == NULL || copy_pos == NULL) { free(node); free(copy_user); free(copy_pos); return false; } strcpy(copy_user, r->user); strcpy(copy_pos, r->position); node->data.user = copy_user; node->data.position = copy_pos; // link new node just behind head node->next = q->head->next; node->prev = q->head; q->head->next->prev = node; q->head->next = node; // update size q->size++; return true; } } void rqueue_remove(rqueue *q, request *r) { if (q != NULL && q->size > 0) { // copy data into reference parameter if (r != NULL) { *r = q->tail->prev->data; } // link around removed node rqueue_node *removed = q->tail->prev; removed->prev->next = q->tail; q->tail->prev = removed->prev; // free removed node free(removed); // update size q->size--; } }