QTip
C library for queues
Loading...
Searching...
No Matches
qtip.c
Go to the documentation of this file.
1
8#include "qtip.h"
9
10#include <string.h>
11
12/*
13 * Private defines
14 */
15
19#define CHECK_NULL_PRT(ptr) (((ptr) != NULL) ? QTIP_STATUS_OK : QTIP_STATUS_NULL_PTR)
20
24#define IS_LOCKED(context) ((!is_locked((context))) ? QTIP_STATUS_OK : QTIP_STATUS_LOCKED)
25
29#define CHECK_STATUS(status, exp) (((status) == QTIP_STATUS_OK) ? (exp) : (status))
30
31/*
32 * Private functions
33 */
34
35static inline void* absolute_index_to_address(qtipContext_t* pContext, qtipSize_t index)
36{
37 return pContext->start + index * pContext->itemSize;
38}
39
40static inline bool is_empty(qtipContext_t* pContext)
41{
42 return pContext->qty == 0U;
43}
44
45static inline bool is_full(qtipContext_t* pContext)
46{
47 return pContext->qty == pContext->maxItems;
48}
49
50static inline qtipSize_t count_items(qtipContext_t* pContext)
51{
52 return pContext->qty;
53}
54
55static inline void write_item_absolute(qtipContext_t* pContext, qtipSize_t index, void* pItem)
56{
57 memcpy(absolute_index_to_address(pContext, index), pItem, pContext->itemSize);
58}
59
60static inline void read_item_absolute(qtipContext_t* pContext, qtipSize_t index, void* pItem)
61{
62 memcpy(pItem, absolute_index_to_address(pContext, index), pContext->itemSize);
63}
64
65static inline void delete_item_absolute(qtipContext_t* pContext, qtipSize_t index)
66{
67 memset(absolute_index_to_address(pContext, index), 0U, pContext->itemSize);
68}
69
70static inline qtipSize_t relative_index_to_absolute(qtipContext_t* pContext, qtipSize_t index)
71{
72 return (pContext->front + index) % pContext->maxItems;
73}
74
75static inline void* relative_index_to_address(qtipContext_t* pContext, qtipSize_t index)
76{
77 return absolute_index_to_address(pContext, relative_index_to_absolute(pContext, index));
78}
79
80static inline void write_item_relative(qtipContext_t* pContext, qtipSize_t index, void* pItem)
81{
82 write_item_absolute(pContext, relative_index_to_absolute(pContext, index), pItem);
83}
84
85static inline void read_item_relative(qtipContext_t* pContext, qtipSize_t index, void* pItem)
86{
87 read_item_absolute(pContext, relative_index_to_absolute(pContext, index), pItem);
88}
89
90static inline void delete_item_relative(qtipContext_t* pContext, qtipSize_t index)
91{
92 delete_item_absolute(pContext, relative_index_to_absolute(pContext, index));
93}
94
95static inline void reset_queue(qtipContext_t* pContext)
96{
97 memset(pContext->start, 0U, pContext->itemSize * pContext->maxItems);
98}
99
100static inline qtipSize_t next_index_absolute(qtipContext_t* pContext, qtipSize_t index)
101{
102 return (index + 1U) % pContext->maxItems;
103}
104
105static inline qtipSize_t next_index_relative(qtipContext_t* pContext, qtipSize_t index)
106{
107 return next_index_absolute(pContext, relative_index_to_absolute(pContext, index));
108}
109
110#ifndef DISABLE_LOCK
111
112static inline bool is_locked(qtipContext_t* pContext)
113{
114 return pContext->locked;
115}
116
117static inline void lock_queue(qtipContext_t* pContext)
118{
119 pContext->locked = true;
120}
121
122static inline void unlock_queue(qtipContext_t* pContext)
123{
124 pContext->locked = false;
125}
126
127#endif // DISABLE_LOCK
128
129static qtipSize_t move_index(qtipContext_t* pContext, qtipSize_t index)
130{
131 qtipSize_t newHeadIndex = index;
132 if (is_empty(pContext))
133 {
134 newHeadIndex = 0U;
135 }
136 else
137 {
138 newHeadIndex = next_index_absolute(pContext, index);
139 }
140
141 return newHeadIndex;
142}
143
144static void sweep_items(qtipContext_t* pContext, qtipSize_t index)
145{
146 void* pHead = relative_index_to_address(pContext, index);
147 qtipSize_t i = 0U;
148
149 for (i = index; i < pContext->qty - 2U; i++)
150 {
151 const void* pNextItem = relative_index_to_address(pContext, i + 1U);
152 memcpy(pHead, pNextItem, pContext->itemSize);
153 pHead = (void*) pNextItem;
154 }
155
156 delete_item_relative(pContext, i + 1U);
157}
158
159/*
160 * Public API
161 */
162
163qtipStatus_t qtip_init(qtipContext_t* pContext, void* pBuffer, qtipSize_t maxItems, size_t itemSize)
164{
166
167#ifndef SKIP_ARG_CHECK
168 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
169 status = CHECK_STATUS(status, CHECK_NULL_PRT(pBuffer));
170 status = CHECK_STATUS(status, (maxItems > 0U) ? QTIP_STATUS_OK : QTIP_STATUS_INVALID_SIZE);
171 status = CHECK_STATUS(status, (itemSize > 0U) ? QTIP_STATUS_OK : QTIP_STATUS_INVALID_SIZE);
172#endif
173
174#ifndef DISABLE_LOCK
175 status = CHECK_STATUS(status, IS_LOCKED(pContext));
176#endif
177
178 if (status == QTIP_STATUS_OK)
179 {
180 pContext->itemSize = itemSize;
181 pContext->maxItems = maxItems;
182 pContext->start = pBuffer;
183 pContext->front = 0U;
184 pContext->rear = 0U;
185 pContext->qty = 0U;
186#ifndef DISABLE_LOCK
187 pContext->locked = false;
188#endif
189#ifndef DISABLE_TELEMETRY
190 pContext->total = 0U;
191 pContext->processed = 0U;
192#endif
193 }
194
195 return status;
196}
197
198qtipStatus_t qtip_put(qtipContext_t* pContext, void* pItem)
199{
201
202#ifndef SKIP_ARG_CHECK
203 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
204 status = CHECK_STATUS(status, CHECK_NULL_PRT(pItem));
205#endif
206
207#ifndef DISABLE_LOCK
208 status = CHECK_STATUS(status, IS_LOCKED(pContext));
209#endif
210
211 if (status == QTIP_STATUS_OK)
212 {
213 if (!is_full(pContext))
214 {
215#ifndef DISABLE_LOCK
216 lock_queue(pContext);
217#endif
218 pContext->rear = move_index(pContext, pContext->rear);
219
220 write_item_absolute(pContext, pContext->rear, pItem);
221 pContext->qty++;
222
223#ifndef DISABLE_TELEMETRY
224 pContext->total++;
225#endif
226
227#ifndef DISABLE_LOCK
228 unlock_queue(pContext);
229#endif
230 }
231 else
232 {
233 status = QTIP_STATUS_FULL;
234 }
235 }
236
237 return status;
238}
239
240qtipStatus_t qtip_pop(qtipContext_t* pContext, void* pItem)
241{
243
244#ifndef SKIP_ARG_CHECK
245 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
246 status = CHECK_STATUS(status, CHECK_NULL_PRT(pItem));
247#endif
248
249#ifndef DISABLE_LOCK
250 status = CHECK_STATUS(status, IS_LOCKED(pContext));
251#endif
252
253 if (status == QTIP_STATUS_OK)
254 {
255 if (!is_empty(pContext))
256 {
257#ifndef DISABLE_LOCK
258 lock_queue(pContext);
259#endif
260 read_item_absolute(pContext, pContext->front, pItem);
261 delete_item_absolute(pContext, pContext->front);
262 pContext->qty--;
263
264 pContext->front = move_index(pContext, pContext->front);
265
266#ifndef DISABLE_TELEMETRY
267 pContext->processed++;
268#endif
269
270#ifndef DISABLE_LOCK
271 unlock_queue(pContext);
272#endif
273 }
274 else
275 {
276 status = QTIP_STATUS_EMPTY;
277 }
278 }
279
280 return status;
281}
282
283qtipStatus_t qtip_peek(qtipContext_t* pContext, void* pBuffer, qtipSize_t* pSize)
284{
286
287#ifndef SKIP_ARG_CHECK
288 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
289 status = CHECK_STATUS(status, CHECK_NULL_PRT(pBuffer));
290 status = CHECK_STATUS(status, CHECK_NULL_PRT(pSize));
291#endif
292
293#ifndef DISABLE_LOCK
294 status = CHECK_STATUS(status, IS_LOCKED(pContext));
295#endif
296
297 if (status == QTIP_STATUS_OK)
298 {
299#ifndef DISABLE_LOCK
300 lock_queue(pContext);
301#endif
302 *pSize = count_items(pContext);
303 for (qtipSize_t i = 0U; i < pContext->qty; i++)
304 {
305 read_item_relative(pContext, i, pBuffer + i * pContext->itemSize);
306 }
307
308#ifndef DISABLE_LOCK
309 unlock_queue(pContext);
310#endif
311 }
312
313 return status;
314}
315
317{
319
320#ifndef SKIP_ARG_CHECK
321 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
322#endif
323
324#ifndef DISABLE_LOCK
325 status = CHECK_STATUS(status, IS_LOCKED(pContext));
326#endif
327
328 if (status == QTIP_STATUS_OK)
329 {
330#ifndef DISABLE_LOCK
331 lock_queue(pContext);
332#endif
333
334 reset_queue(pContext);
335 pContext->qty = 0U;
336 pContext->front = move_index(pContext, pContext->front);
337 pContext->rear = move_index(pContext, pContext->rear);
338
339#ifndef DISABLE_LOCK
340 unlock_queue(pContext);
341#endif
342 }
343
344 return status;
345}
346
348{
350
351#ifndef SKIP_ARG_CHECK
352 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
353 status = CHECK_STATUS(status, CHECK_NULL_PRT(pItem));
354#endif
355
356#ifndef DISABLE_LOCK
357 status = CHECK_STATUS(status, IS_LOCKED(pContext));
358#endif
359
360 if (status == QTIP_STATUS_OK)
361 {
362 if (!is_empty(pContext))
363 {
364#ifndef DISABLE_LOCK
365 lock_queue(pContext);
366#endif
367
368 read_item_absolute(pContext, pContext->rear, pItem);
369
370#ifndef DISABLE_LOCK
371 unlock_queue(pContext);
372#endif
373 }
374 else
375 {
376 status = QTIP_STATUS_EMPTY;
377 }
378 }
379
380 return status;
381}
382
384{
386
387#ifndef SKIP_ARG_CHECK
388 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
389 status = CHECK_STATUS(status, CHECK_NULL_PRT(pItem));
390#endif
391
392#ifndef DISABLE_LOCK
393 status = CHECK_STATUS(status, IS_LOCKED(pContext));
394#endif
395
396 if (status == QTIP_STATUS_OK)
397 {
398 if (!is_empty(pContext))
399 {
400#ifndef DISABLE_LOCK
401 lock_queue(pContext);
402#endif
403
404 read_item_absolute(pContext, pContext->front, pItem);
405
406#ifndef DISABLE_LOCK
407 unlock_queue(pContext);
408#endif
409 }
410 else
411 {
412 status = QTIP_STATUS_EMPTY;
413 }
414 }
415
416 return status;
417}
418
419#ifndef DISABLE_LOCK
420
422{
424
425#ifndef SKIP_ARG_CHECK
426 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
427#endif
428
429 if (status == QTIP_STATUS_OK)
430 {
431 status = IS_LOCKED(pContext);
432 }
433
434 return status;
435}
436
438{
440
441#ifndef SKIP_ARG_CHECK
442 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
443#endif
444
445 if (status == QTIP_STATUS_OK)
446 {
447 lock_queue(pContext);
448 }
449
450 return status;
451}
452
454{
456
457#ifndef SKIP_ARG_CHECK
458 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
459#endif
460
461 if (status == QTIP_STATUS_OK)
462 {
463 unlock_queue(pContext);
464 }
465
466 return status;
467}
468
469#endif // DISABLE_LOCK
470
471#ifndef REDUCED_API
473{
475
476#ifndef SKIP_ARG_CHECK
477 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
478#endif
479
480 if (status == QTIP_STATUS_OK)
481 {
482 status = (is_full(pContext)) ? QTIP_STATUS_FULL : QTIP_STATUS_OK;
483 }
484
485 return status;
486}
487
489{
491
492#ifndef SKIP_ARG_CHECK
493 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
494#endif
495
496 if (status == QTIP_STATUS_OK)
497 {
498 status = (is_empty(pContext)) ? QTIP_STATUS_FULL : QTIP_STATUS_OK;
499 }
500
501 return status;
502}
503
505{
507
508#ifndef SKIP_ARG_CHECK
509 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
510#endif
511
512 if (status == QTIP_STATUS_OK)
513 {
514 *pResult = count_items(pContext);
515 }
516
517 return status;
518}
519
521{
523
524#ifndef SKIP_ARG_CHECK
525 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
526 status = CHECK_STATUS(status, CHECK_NULL_PRT(pItem));
527#endif
528
529#ifndef DISABLE_LOCK
530 status = CHECK_STATUS(status, IS_LOCKED(pContext));
531#endif
532
533 status = CHECK_STATUS(status, (index <= pContext->qty) ? QTIP_STATUS_OK : QTIP_STATUS_INVALID_SIZE);
534
535 if (status == QTIP_STATUS_OK)
536 {
537 read_item_relative(pContext, index, pItem);
538 }
539
540 return status;
541}
542
544{
546
547#ifndef SKIP_ARG_CHECK
548 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
549#endif
550
551#ifndef DISABLE_LOCK
552 status = CHECK_STATUS(status, IS_LOCKED(pContext));
553#endif
554
555 status = CHECK_STATUS(status, (index <= pContext->qty) ? QTIP_STATUS_OK : QTIP_STATUS_INVALID_SIZE);
556
557 if (status == QTIP_STATUS_OK)
558 {
559 delete_item_relative(pContext, index);
560 sweep_items(pContext, index);
561 pContext->qty--;
562 }
563
564 return status;
565}
566
568{
570
571#ifndef SKIP_ARG_CHECK
572 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
573 status = CHECK_STATUS(status, CHECK_NULL_PRT(pItem));
574#endif
575
576#ifndef DISABLE_LOCK
577 status = CHECK_STATUS(status, IS_LOCKED(pContext));
578#endif
579
580 status = CHECK_STATUS(status, (index <= pContext->qty) ? QTIP_STATUS_OK : QTIP_STATUS_INVALID_SIZE);
581
582 if (status == QTIP_STATUS_OK)
583 {
584 read_item_relative(pContext, index, pItem);
585 delete_item_relative(pContext, index);
586 sweep_items(pContext, index);
587 pContext->qty--;
588 }
589
590 return status;
591}
592
593#endif // REDUCED_API
594
595#ifndef DISABLE_TELEMETRY
596
598{
600
601#ifndef SKIP_ARG_CHECK
602 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
603 status = CHECK_STATUS(status, CHECK_NULL_PRT(pResult));
604#endif
605
606 if (status == QTIP_STATUS_OK)
607 {
608 *pResult = pContext->total;
609 }
610
611 return status;
612}
613
615{
617
618#ifndef SKIP_ARG_CHECK
619 status = CHECK_STATUS(status, CHECK_NULL_PRT(pContext));
620 status = CHECK_STATUS(status, CHECK_NULL_PRT(pResult));
621#endif
622
623 if (status == QTIP_STATUS_OK)
624 {
625 *pResult = pContext->processed;
626 }
627
628 return status;
629}
630
631#endif // DISABLE_TELEMETRY
bool locked
Lock status.
Definition qtip.h:80
qtipSize_t rear
Absolute index of the rear of the queue.
Definition qtip.h:77
qtipSize_t maxItems
Number of items allowed in the queue.
Definition qtip.h:73
size_t total
Number of items introduced to the queue.
Definition qtip.h:84
qtipSize_t qty
Current number of items in the queue.
Definition qtip.h:74
void * start
Pointer to the start of the queue.
Definition qtip.h:75
size_t itemSize
Size of each item in the queue.
Definition qtip.h:78
size_t processed
Number of items removed from the queue.
Definition qtip.h:83
qtipSize_t front
Absolute index of the front of the queue.
Definition qtip.h:76
qtipStatus_t qtip_put(qtipContext_t *pContext, void *pItem)
Put an item in a queue.
Definition qtip.c:198
qtipStatus_t qtip_count_items(qtipContext_t *pContext, qtipSize_t *pResult)
Gets the number of items in the queue.
Definition qtip.c:504
qtipStatus_t qtip_is_full(qtipContext_t *pContext)
Checks whether the queue is full.
Definition qtip.c:472
size_t qtipSize_t
Number of items in queue.
Definition qtip.h:45
qtipStatus_t qtip_get_front(qtipContext_t *pContext, void *pItem)
Gets the item at the front of the queue.
Definition qtip.c:383
qtipStatus_t
Queue operation status.
Definition qtip.h:55
qtipStatus_t qtip_unlock(qtipContext_t *pContext)
Unlocks the queue.
Definition qtip.c:453
qtipStatus_t qtip_total_processed_items(qtipContext_t *pContext, size_t *pResult)
Get number of processed items in the queue.
Definition qtip.c:614
qtipStatus_t qtip_get_rear(qtipContext_t *pContext, void *pItem)
Gets the item at the rear of the queue.
Definition qtip.c:347
qtipStatus_t qtip_pop(qtipContext_t *pContext, void *pItem)
Extract the next item from the queue.
Definition qtip.c:240
qtipStatus_t qtip_peek(qtipContext_t *pContext, void *pBuffer, qtipSize_t *pSize)
Copies every element of the queue into a buffer.
Definition qtip.c:283
qtipStatus_t qtip_is_empty(qtipContext_t *pContext)
Checks whether the queue is empty.
Definition qtip.c:488
qtipStatus_t qtip_is_locked(qtipContext_t *pContext)
Checks whether the queue is locked.
Definition qtip.c:421
qtipStatus_t qtip_remove_item_index(qtipContext_t *pContext, qtipSize_t index)
Removes the item from an intex in the queue.
Definition qtip.c:543
qtipStatus_t qtip_purge(qtipContext_t *pContext)
Removes all the items from the queue.
Definition qtip.c:316
qtipStatus_t qtip_total_enqueued_items(qtipContext_t *pContext, size_t *pResult)
Get number of items inserted in the queue.
Definition qtip.c:597
qtipStatus_t qtip_init(qtipContext_t *pContext, void *pBuffer, qtipSize_t maxItems, size_t itemSize)
Initialize queue context.
Definition qtip.c:163
qtipStatus_t qtip_get_item_index(qtipContext_t *pContext, qtipSize_t index, void *pItem)
Gets the item from an intex in the queue.
Definition qtip.c:520
qtipStatus_t qtip_get_pop_index(qtipContext_t *pContext, qtipSize_t index, void *pItem)
Pops the item from an intex in the queue.
Definition qtip.c:567
qtipStatus_t qtip_lock(qtipContext_t *pContext)
Locks the queue.
Definition qtip.c:437
@ QTIP_STATUS_EMPTY
Queue is empty.
Definition qtip.h:58
@ QTIP_STATUS_INVALID_SIZE
Invalid queue size.
Definition qtip.h:60
@ QTIP_STATUS_OK
Operation succeded.
Definition qtip.h:56
@ QTIP_STATUS_FULL
Queue is full.
Definition qtip.h:57
Queue context structure.
Definition qtip.h:72
#define CHECK_NULL_PRT(ptr)
Check whether the input is a null pointer.
Definition qtip.c:19
#define IS_LOCKED(context)
Check whether the queue is locked.
Definition qtip.c:24
#define CHECK_STATUS(status, exp)
Combine the current status with a new expression.
Definition qtip.c:29
API for queues.