source: mainline/uspace/lib/c/generic/adt/dynamic_fifo.c@ 4eca056

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4eca056 was 4eca056, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Remove xxx_ref typedefs (part 4).

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (c) 2009 Lukas Mejdrech
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32
33/** @file
34 * Dynamic first in first out positive integer queue implementation.
35 */
36
37#include <adt/dynamic_fifo.h>
38
39#include <errno.h>
40#include <malloc.h>
41#include <mem.h>
42
43/** Internal magic value for a consistency check. */
44#define DYN_FIFO_MAGIC_VALUE 0x58627659
45
46/** Returns the next queue index.
47 *
48 * The queue field is circular.
49 *
50 * @param[in] fifo The dynamic queue.
51 * @param[in] index The actual index to be shifted.
52 */
53#define NEXT_INDEX(fifo, index) (((index) + 1) % ((fifo)->size + 1))
54
55/** Checks if the queue is valid.
56 *
57 * @param[in] fifo The dynamic queue.
58 * @returns TRUE if the queue is valid.
59 * @returns FALSE otherwise.
60 */
61static int dyn_fifo_is_valid(dyn_fifo_t *fifo)
62{
63 return fifo && (fifo->magic_value == DYN_FIFO_MAGIC_VALUE);
64}
65
66/** Initializes the dynamic queue.
67 *
68 * @param[in,out] fifo The dynamic queue.
69 * @param[in] size The initial queue size.
70 * @returns EOK on success.
71 * @returns EINVAL if the queue is not valid.
72 * @returns EBADMEM if the fifo parameter is NULL.
73 * @returns ENOMEM if there is not enough memory left.
74 */
75int dyn_fifo_initialize(dyn_fifo_t *fifo, int size)
76{
77 if (!fifo)
78 return EBADMEM;
79
80 if (size <= 0)
81 return EINVAL;
82
83 fifo->items = (int *) malloc(sizeof(int) * size + 1);
84 if (!fifo->items)
85 return ENOMEM;
86
87 fifo->size = size;
88 fifo->head = 0;
89 fifo->tail = 0;
90 fifo->magic_value = DYN_FIFO_MAGIC_VALUE;
91
92 return EOK;
93}
94
95/** Appends a new item to the queue end.
96 *
97 * @param[in,out] fifo The dynamic queue.
98 * @param[in] value The new item value. Should be positive.
99 * @param[in] max_size The maximum queue size. The queue is not resized beyound
100 * this limit. May be zero or negative to indicate no
101 * limit.
102 * @returns EOK on success.
103 * @returns EINVAL if the queue is not valid.
104 * @returns ENOMEM if there is not enough memory left.
105 */
106int dyn_fifo_push(dyn_fifo_t *fifo, int value, int max_size)
107{
108 int *new_items;
109
110 if (!dyn_fifo_is_valid(fifo))
111 return EINVAL;
112
113 if (NEXT_INDEX(fifo, fifo->tail) == fifo->head) {
114 if ((max_size > 0) && ((fifo->size * 2) > max_size)) {
115 if(fifo->size >= max_size)
116 return ENOMEM;
117 } else {
118 max_size = fifo->size * 2;
119 }
120
121 new_items = realloc(fifo->items, sizeof(int) * max_size + 1);
122 if (!new_items)
123 return ENOMEM;
124
125 fifo->items = new_items;
126 if (fifo->tail < fifo->head) {
127 if (fifo->tail < max_size - fifo->size) {
128 memcpy(fifo->items + fifo->size + 1,
129 fifo->items, fifo->tail * sizeof(int));
130 fifo->tail += fifo->size + 1;
131 } else {
132 memcpy(fifo->items + fifo->size + 1,
133 fifo->items,
134 (max_size - fifo->size) * sizeof(int));
135 memcpy(fifo->items,
136 fifo->items + max_size - fifo->size,
137 fifo->tail - max_size + fifo->size);
138 fifo->tail -= max_size - fifo->size;
139 }
140 }
141 fifo->size = max_size;
142 }
143
144 fifo->items[fifo->tail] = value;
145 fifo->tail = NEXT_INDEX(fifo, fifo->tail);
146 return EOK;
147}
148
149/** Returns and excludes the first item in the queue.
150 *
151 * @param[in,out] fifo The dynamic queue.
152 * @returns Value of the first item in the queue.
153 * @returns EINVAL if the queue is not valid.
154 * @returns ENOENT if the queue is empty.
155 */
156int dyn_fifo_pop(dyn_fifo_t *fifo)
157{
158 int value;
159
160 if (!dyn_fifo_is_valid(fifo))
161 return EINVAL;
162
163 if (fifo->head == fifo->tail)
164 return ENOENT;
165
166 value = fifo->items[fifo->head];
167 fifo->head = NEXT_INDEX(fifo, fifo->head);
168 return value;
169}
170
171/** Returns and keeps the first item in the queue.
172 *
173 * @param[in,out] fifo The dynamic queue.
174 * @returnsi Value of the first item in the queue.
175 * @returns EINVAL if the queue is not valid.
176 * @returns ENOENT if the queue is empty.
177 */
178int dyn_fifo_value(dyn_fifo_t *fifo)
179{
180 if (!dyn_fifo_is_valid(fifo))
181 return EINVAL;
182
183 if (fifo->head == fifo->tail)
184 return ENOENT;
185
186 return fifo->items[fifo->head];
187}
188
189/** Clears and destroys the queue.
190 *
191 * @param[in,out] fifo The dynamic queue.
192 * @returns EOK on success.
193 * @returns EINVAL if the queue is not valid.
194 */
195int dyn_fifo_destroy(dyn_fifo_t *fifo)
196{
197 if (!dyn_fifo_is_valid(fifo))
198 return EINVAL;
199
200 free(fifo->items);
201 fifo->magic_value = 0;
202 return EOK;
203}
204
205/** @}
206 */
Note: See TracBrowser for help on using the repository browser.