mirror of
https://github.com/SELinuxProject/selinux
synced 2024-12-22 05:59:58 +00:00
181 lines
2.5 KiB
C
181 lines
2.5 KiB
C
|
|
||
|
/* 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 */
|