diff options
Diffstat (limited to 'checkpolicy/queue.c')
-rw-r--r-- | checkpolicy/queue.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/checkpolicy/queue.c b/checkpolicy/queue.c new file mode 100644 index 00000000..272079c0 --- /dev/null +++ b/checkpolicy/queue.c @@ -0,0 +1,180 @@ + +/* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */ + +/* FLASK */ + +/* + * Implementation of the double-ended queue type. + */ + +#include <stdlib.h> +#include "queue.h" + +queue_t queue_create(void) +{ + queue_t q; + + q = (queue_t) malloc(sizeof(struct queue_info)); + if (q == NULL) + return NULL; + + q->head = q->tail = NULL; + + return q; +} + +int queue_insert(queue_t q, queue_element_t e) +{ + queue_node_ptr_t newnode; + + if (!q) + return -1; + + newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node)); + if (newnode == NULL) + return -1; + + newnode->element = e; + newnode->next = NULL; + + if (q->head == NULL) { + q->head = q->tail = newnode; + } else { + q->tail->next = newnode; + q->tail = newnode; + } + + return 0; +} + +int queue_push(queue_t q, queue_element_t e) +{ + queue_node_ptr_t newnode; + + if (!q) + return -1; + + newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node)); + if (newnode == NULL) + return -1; + + newnode->element = e; + newnode->next = NULL; + + if (q->head == NULL) { + q->head = q->tail = newnode; + } else { + newnode->next = q->head; + q->head = newnode; + } + + return 0; +} + +queue_element_t queue_remove(queue_t q) +{ + queue_node_ptr_t node; + queue_element_t e; + + if (!q) + return NULL; + + if (q->head == NULL) + return NULL; + + node = q->head; + q->head = q->head->next; + if (q->head == NULL) + q->tail = NULL; + + e = node->element; + free(node); + + return e; +} + +queue_element_t queue_head(queue_t q) +{ + if (!q) + return NULL; + + if (q->head == NULL) + return NULL; + + return q->head->element; +} + +void queue_destroy(queue_t q) +{ + queue_node_ptr_t p, temp; + + if (!q) + return; + + p = q->head; + while (p != NULL) { + temp = p; + p = p->next; + free(temp); + } + + free(q); +} + +int queue_map(queue_t q, int (*f) (queue_element_t, void *), void *vp) +{ + queue_node_ptr_t p; + int ret; + + if (!q) + return 0; + + p = q->head; + while (p != NULL) { + ret = f(p->element, vp); + if (ret) + return ret; + p = p->next; + } + return 0; +} + +void queue_map_remove_on_error(queue_t q, + int (*f) (queue_element_t, void *), + void (*g) (queue_element_t, void *), void *vp) +{ + queue_node_ptr_t p, last, temp; + int ret; + + if (!q) + return; + + last = NULL; + p = q->head; + while (p != NULL) { + ret = f(p->element, vp); + if (ret) { + if (last) { + last->next = p->next; + if (last->next == NULL) + q->tail = last; + } else { + q->head = p->next; + if (q->head == NULL) + q->tail = NULL; + } + + temp = p; + p = p->next; + g(temp->element, vp); + free(temp); + } else { + last = p; + p = p->next; + } + } + + return; +} + +/* FLASK */ |