1 
2 /* Author : Stephen Smalley, <sds@epoch.ncsc.mil> */
3 
4 /* FLASK */
5 
6 /*
7  * Implementation of the double-ended queue type.
8  */
9 
10 #include <stdlib.h>
11 #include "queue.h"
12 
queue_create(void)13 queue_t queue_create(void)
14 {
15 	queue_t q;
16 
17 	q = (queue_t) malloc(sizeof(struct queue_info));
18 	if (q == NULL)
19 		return NULL;
20 
21 	q->head = q->tail = NULL;
22 
23 	return q;
24 }
25 
queue_insert(queue_t q,queue_element_t e)26 int queue_insert(queue_t q, queue_element_t e)
27 {
28 	queue_node_ptr_t newnode;
29 
30 	if (!q)
31 		return -1;
32 
33 	newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node));
34 	if (newnode == NULL)
35 		return -1;
36 
37 	newnode->element = e;
38 	newnode->next = NULL;
39 
40 	if (q->head == NULL) {
41 		q->head = q->tail = newnode;
42 	} else {
43 		q->tail->next = newnode;
44 		q->tail = newnode;
45 	}
46 
47 	return 0;
48 }
49 
queue_push(queue_t q,queue_element_t e)50 int queue_push(queue_t q, queue_element_t e)
51 {
52 	queue_node_ptr_t newnode;
53 
54 	if (!q)
55 		return -1;
56 
57 	newnode = (queue_node_ptr_t) malloc(sizeof(struct queue_node));
58 	if (newnode == NULL)
59 		return -1;
60 
61 	newnode->element = e;
62 	newnode->next = NULL;
63 
64 	if (q->head == NULL) {
65 		q->head = q->tail = newnode;
66 	} else {
67 		newnode->next = q->head;
68 		q->head = newnode;
69 	}
70 
71 	return 0;
72 }
73 
queue_remove(queue_t q)74 queue_element_t queue_remove(queue_t q)
75 {
76 	queue_node_ptr_t node;
77 	queue_element_t e;
78 
79 	if (!q)
80 		return NULL;
81 
82 	if (q->head == NULL)
83 		return NULL;
84 
85 	node = q->head;
86 	q->head = q->head->next;
87 	if (q->head == NULL)
88 		q->tail = NULL;
89 
90 	e = node->element;
91 	free(node);
92 
93 	return e;
94 }
95 
queue_head(queue_t q)96 queue_element_t queue_head(queue_t q)
97 {
98 	if (!q)
99 		return NULL;
100 
101 	if (q->head == NULL)
102 		return NULL;
103 
104 	return q->head->element;
105 }
106 
queue_destroy(queue_t q)107 void queue_destroy(queue_t q)
108 {
109 	queue_node_ptr_t p, temp;
110 
111 	if (!q)
112 		return;
113 
114 	p = q->head;
115 	while (p != NULL) {
116 		temp = p;
117 		p = p->next;
118 		free(temp);
119 	}
120 
121 	free(q);
122 }
123 
queue_map(queue_t q,int (* f)(queue_element_t,void *),void * vp)124 int queue_map(queue_t q, int (*f) (queue_element_t, void *), void *vp)
125 {
126 	queue_node_ptr_t p;
127 	int ret;
128 
129 	if (!q)
130 		return 0;
131 
132 	p = q->head;
133 	while (p != NULL) {
134 		ret = f(p->element, vp);
135 		if (ret)
136 			return ret;
137 		p = p->next;
138 	}
139 	return 0;
140 }
141 
queue_map_remove_on_error(queue_t q,int (* f)(queue_element_t,void *),void (* g)(queue_element_t,void *),void * vp)142 void queue_map_remove_on_error(queue_t q,
143 			       int (*f) (queue_element_t, void *),
144 			       void (*g) (queue_element_t, void *), void *vp)
145 {
146 	queue_node_ptr_t p, last, temp;
147 	int ret;
148 
149 	if (!q)
150 		return;
151 
152 	last = NULL;
153 	p = q->head;
154 	while (p != NULL) {
155 		ret = f(p->element, vp);
156 		if (ret) {
157 			if (last) {
158 				last->next = p->next;
159 				if (last->next == NULL)
160 					q->tail = last;
161 			} else {
162 				q->head = p->next;
163 				if (q->head == NULL)
164 					q->tail = NULL;
165 			}
166 
167 			temp = p;
168 			p = p->next;
169 			g(temp->element, vp);
170 			free(temp);
171 		} else {
172 			last = p;
173 			p = p->next;
174 		}
175 	}
176 
177 	return;
178 }
179 
180 /* FLASK */
181