Skip to content

Commit 91140b2

Browse files
authored
Feature/prevent items from other queues (#4)
* Avoid ereasing items from another queue * Add getNumberOfItems function * Add a forEach function
1 parent 73faca6 commit 91140b2

3 files changed

Lines changed: 592 additions & 13 deletions

File tree

src/static_queue.c

Lines changed: 107 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,13 @@ int32_t staticQueueErase(staticQueue_t* queue, staticQueueItem_t* item)
135135
item->active = false;
136136

137137
// Special case: if this was the only item in the queue
138-
if (queue->tail == queue->head->last) {
138+
if (queue->tail == queue->head->last && queue->tail == item) {
139139
// Queue is now empty, reset pointers
140140
queue->head = queue->first_item;
141141
queue->tail = queue->first_item;
142142
return STATIC_QUEUE_SUCCESS;
143-
}
144-
145-
// If erasing the tail item (oldest item), just move tail to next
146-
if (item == queue->tail) {
143+
} else if (item == queue->tail) {
144+
// If erasing the tail item (oldest item), just move tail to next
147145
queue->tail = queue->tail->next;
148146

149147
// Skip over any remaining inactive items at tail
@@ -158,10 +156,8 @@ int32_t staticQueueErase(staticQueue_t* queue, staticQueueItem_t* item)
158156
}
159157

160158
return STATIC_QUEUE_SUCCESS;
161-
}
162-
163-
// If erasing the item just before head (newest item), move head backward
164-
if (item->next == queue->head) {
159+
} else if (item->next == queue->head) {
160+
// If erasing the item just before head (newest item), move head backward
165161
queue->head = item;
166162

167163
// Check if head caught up to tail with exactly one active item
@@ -173,7 +169,24 @@ int32_t staticQueueErase(staticQueue_t* queue, staticQueueItem_t* item)
173169
return STATIC_QUEUE_SUCCESS;
174170
}
175171

176-
// For items in the middle: remove from current position and relink immediately before tail
172+
// For items in the middle: first verify the item is actually in the queue
173+
// We can start from the element one from the tail as we have allready checked the tail item above.
174+
staticQueueItem_t* current = queue->tail->next;
175+
bool found = false;
176+
177+
// Traverse from tail to head to find the item
178+
while (current != queue->head) {
179+
if (current == item) {
180+
found = true;
181+
break;
182+
}
183+
current = current->next;
184+
}
185+
186+
// If not found, the item is not in this queue
187+
if (!found) {
188+
return STATIC_QUEUE_NOT_IN_QUEUE;
189+
}
177190

178191
// Step 1: Remove item from its current position in the list
179192
staticQueueItem_t* prev_item = item->last;
@@ -198,3 +211,87 @@ int32_t staticQueueErase(staticQueue_t* queue, staticQueueItem_t* item)
198211

199212
return STATIC_QUEUE_SUCCESS;
200213
}
214+
215+
int32_t staticQueueGetNumItems(staticQueue_t* queue)
216+
{
217+
if (queue == NULL) {
218+
return STATIC_QUEUE_EMPTY;
219+
}
220+
221+
if (staticQueueEmpty(queue)) {
222+
return 0;
223+
}
224+
225+
// Check if queue is full
226+
if (staticQueuefull(queue)) {
227+
return queue->queue_length;
228+
}
229+
230+
// Count active items from tail to head
231+
int32_t count = 0;
232+
staticQueueItem_t *current = queue->tail;
233+
234+
while (current != queue->head) {
235+
if (current->active) {
236+
count++;
237+
}
238+
current = current->next;
239+
}
240+
241+
return count;
242+
}
243+
244+
int32_t staticQueueForEach(staticQueue_t* queue, int32_t (*callback)(staticQueue_t *queue, staticQueueItem_t *item))
245+
{
246+
if (queue == NULL || callback == NULL) {
247+
return STATIC_QUEUE_EMPTY;
248+
}
249+
250+
if (staticQueueEmpty(queue)) {
251+
return STATIC_QUEUE_SUCCESS;
252+
}
253+
254+
// Get the number of items to process
255+
int32_t num_items = staticQueueGetNumItems(queue);
256+
if (num_items <= 0) {
257+
return STATIC_QUEUE_SUCCESS;
258+
}
259+
260+
staticQueueItem_t *current = queue->tail;
261+
int32_t processed = 0;
262+
263+
// Process exactly num_items active items
264+
while (processed < num_items) {
265+
// Only process active items
266+
if (current->active) {
267+
int32_t cb_res = callback(queue, current);
268+
switch(cb_res) {
269+
case STATIC_QUEUE_CB_NEXT:
270+
current = current->next;
271+
processed++;
272+
break;
273+
case STATIC_QUEUE_CB_STOP:
274+
return STATIC_QUEUE_SUCCESS;
275+
case STATIC_QUEUE_CB_ERASE: {
276+
staticQueueItem_t *tmp = current;
277+
current = current->next;
278+
processed++;
279+
// Erase this item from the queue
280+
if ((cb_res = staticQueueErase(queue, tmp)) != STATIC_QUEUE_SUCCESS) {
281+
return cb_res;
282+
}
283+
// Check if queue is now empty after erase
284+
if (staticQueueEmpty(queue)) {
285+
return STATIC_QUEUE_SUCCESS;
286+
}
287+
} break;
288+
default:
289+
return cb_res;
290+
}
291+
} else {
292+
current = current->next;
293+
}
294+
}
295+
296+
return STATIC_QUEUE_SUCCESS;
297+
}

src/static_queue.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,18 @@
7979

8080
// Package queue
8181
typedef enum {
82-
STATIC_QUEUE_SUCCESS = 0,
83-
STATIC_QUEUE_FULL = -401,
84-
STATIC_QUEUE_EMPTY = -402,
82+
STATIC_QUEUE_SUCCESS = 0,
83+
STATIC_QUEUE_FULL = -401,
84+
STATIC_QUEUE_EMPTY = -402,
85+
STATIC_QUEUE_NOT_IN_QUEUE = -403,
8586
} queueErr_t;
8687

88+
typedef enum {
89+
STATIC_QUEUE_CB_NEXT = 0, // Keep iterating
90+
STATIC_QUEUE_CB_STOP, // Stop iterating
91+
STATIC_QUEUE_CB_ERASE, // Erase this node and keep iterating
92+
} staticQueueCbDo_t;
93+
8794
typedef struct staticQueueItem staticQueueItem_t;
8895

8996
struct staticQueueItem {
@@ -173,6 +180,21 @@ bool staticQueuefull(staticQueue_t* queue);
173180
*/
174181
bool staticQueueEmpty(staticQueue_t* queue);
175182

183+
/**
184+
* Get the number of active items in the queue
185+
* Input: Queue instance
186+
* Returns: Number of items in queue, or negative error code
187+
*/
188+
int32_t staticQueueGetNumItems(staticQueue_t* queue);
189+
190+
/**
191+
* Loop through all items in queue and call the callback on each
192+
* Input: Queue instance
193+
* Input: Callback function
194+
* Returns: queueErr_t
195+
*/
196+
int32_t staticQueueForEach(staticQueue_t* queue, int32_t (*callback)(staticQueue_t *queue, staticQueueItem_t *item));
197+
176198
/**
177199
* This is a macro that makes it more safe to initialize a queue
178200
*/

0 commit comments

Comments
 (0)