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
13queue_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
26int 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
50int 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
74queue_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
96queue_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
107void 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
124int 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
142void 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