-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
53a101f
commit 425c628
Showing
6 changed files
with
583 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/*! | ||
* @file | ||
* @brief FIFO queue for arbitrarily-sized elements. | ||
*/ | ||
|
||
#ifndef tiny_queue_h | ||
#define tiny_queue_h | ||
|
||
#include <stddef.h> | ||
#include <stdint.h> | ||
#include "tiny_ring_buffer.h" | ||
|
||
typedef struct { | ||
uint16_t element_count; | ||
tiny_ring_buffer_t ring_buffer; | ||
} tiny_queue_t; | ||
|
||
/*! | ||
* Initialize a queue with the provided buffer. | ||
*/ | ||
void tiny_queue_init( | ||
tiny_queue_t* self, | ||
void* buffer, | ||
size_t buffer_size); | ||
|
||
/*! | ||
* Add an element to the queue. Returns true if the element was successfully enqueued, false otherwise | ||
*/ | ||
bool tiny_queue_enqueue(tiny_queue_t* self, const void* element, uint16_t size); | ||
|
||
/*! | ||
* Remove an element from the queue and copy it into the provided element buffer. | ||
* @pre The queue is not empty | ||
*/ | ||
void tiny_queue_dequeue(tiny_queue_t* self, void* element, uint16_t* size); | ||
|
||
/*! | ||
* Similar to Dequeue but the element is not retrieved. | ||
* @pre The queue is not empty | ||
*/ | ||
void tiny_queue_discard(tiny_queue_t* self); | ||
|
||
/*! | ||
* Peeks an element from the queue without removing it and copies it into the provided element buffer. | ||
* @pre 0 <= index < The count of elements in the queue | ||
*/ | ||
void tiny_queue_peek(tiny_queue_t* self, void* element, uint16_t* size, uint16_t index); | ||
|
||
/*! | ||
* Peek part of an element. Only copies out up to the specified number of bytes. | ||
* @pre 0 <= index < The count of elements in the queue | ||
*/ | ||
void tiny_queue_peek_partial(tiny_queue_t* self, void* element, uint16_t size_limit, uint16_t index); | ||
|
||
/*! | ||
* Peek part of an element. Only copies out up to the specified number of bytes. | ||
* @pre 0 <= index < The count of elements in the queue | ||
*/ | ||
void tiny_queue_peek_size(tiny_queue_t* self, uint16_t* size, uint16_t index); | ||
|
||
/*! | ||
* Get the number of elements in the queue. | ||
*/ | ||
uint16_t tiny_queue_count(tiny_queue_t* self); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/*! | ||
* @file | ||
* @brief | ||
*/ | ||
|
||
#include "tiny_queue.h" | ||
|
||
static void insert_element_size(tiny_queue_t* self, uint16_t element_size) | ||
{ | ||
uint8_t* destination = (uint8_t*)&element_size; | ||
for(uint16_t i = 0; i < sizeof(uint16_t); i++) { | ||
tiny_ring_buffer_insert(&self->ring_buffer, destination); | ||
destination++; | ||
} | ||
} | ||
|
||
static void insert_element(tiny_queue_t* self, const void* element, uint16_t element_size) | ||
{ | ||
const uint8_t* source = element; | ||
for(uint16_t i = 0; i < element_size; i++) { | ||
tiny_ring_buffer_insert(&self->ring_buffer, source); | ||
source++; | ||
} | ||
} | ||
|
||
static void remove_element_size(tiny_queue_t* self, uint16_t* sizePlaceHolder) | ||
{ | ||
uint8_t* destination = (uint8_t*)sizePlaceHolder; | ||
for(uint16_t i = 0; i < sizeof(uint16_t); i++) { | ||
tiny_ring_buffer_remove(&self->ring_buffer, destination); | ||
destination++; | ||
} | ||
} | ||
|
||
static void remove_element(tiny_queue_t* self, void* element, uint16_t element_size) | ||
{ | ||
uint8_t* destination = element; | ||
for(uint16_t i = 0; i < element_size; i++) { | ||
tiny_ring_buffer_remove(&self->ring_buffer, destination); | ||
destination++; | ||
} | ||
} | ||
|
||
static void discard_element(tiny_queue_t* self, uint16_t element_size) | ||
{ | ||
for(uint16_t i = 0; i < element_size; i++) { | ||
uint8_t discard; | ||
tiny_ring_buffer_remove(&self->ring_buffer, &discard); | ||
} | ||
} | ||
|
||
static void peek_element_size_at_ring_buffer_index(tiny_queue_t* self, uint16_t* element_size, uint16_t location) | ||
{ | ||
uint8_t* destination = (uint8_t*)element_size; | ||
for(uint16_t i = location; i < location + sizeof(uint16_t); i++) { | ||
tiny_ring_buffer_at(&self->ring_buffer, i, destination); | ||
destination++; | ||
} | ||
} | ||
|
||
static uint16_t ring_buffer_index_for_element_index(tiny_queue_t* self, uint16_t element_index) | ||
{ | ||
uint16_t element_size; | ||
uint16_t location = 0; | ||
for(uint16_t i = 0; i < element_index; i++) { | ||
peek_element_size_at_ring_buffer_index(self, &element_size, location); | ||
location += element_size + sizeof(uint16_t); | ||
} | ||
return location; | ||
} | ||
|
||
static void peek_element_at_ring_buffer_index(tiny_queue_t* self, void* element, uint16_t element_size, uint16_t location) | ||
{ | ||
uint8_t* destination = element; | ||
for(uint16_t i = location; i < location + element_size; i++) { | ||
tiny_ring_buffer_at(&self->ring_buffer, i, destination); | ||
destination++; | ||
} | ||
} | ||
|
||
bool tiny_queue_enqueue(tiny_queue_t* self, const void* element, uint16_t element_size) | ||
{ | ||
size_t required_space = element_size + sizeof(uint16_t); | ||
size_t available_space = tiny_ring_buffer_capacity(&self->ring_buffer) - tiny_ring_buffer_count(&self->ring_buffer); | ||
|
||
if(required_space <= available_space) { | ||
insert_element_size(self, element_size); | ||
insert_element(self, element, element_size); | ||
self->element_count++; | ||
return true; | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
|
||
void tiny_queue_dequeue(tiny_queue_t* self, void* element, uint16_t* sizeStorage) | ||
{ | ||
remove_element_size(self, sizeStorage); | ||
remove_element(self, element, *sizeStorage); | ||
self->element_count--; | ||
} | ||
|
||
void tiny_queue_discard(tiny_queue_t* self) | ||
{ | ||
uint16_t sizeStorage; | ||
remove_element_size(self, &sizeStorage); | ||
discard_element(self, sizeStorage); | ||
self->element_count--; | ||
} | ||
|
||
void tiny_queue_peek(tiny_queue_t* self, void* element, uint16_t* sizeStorage, uint16_t element_index) | ||
{ | ||
uint16_t i = ring_buffer_index_for_element_index(self, element_index); | ||
peek_element_size_at_ring_buffer_index(self, sizeStorage, i); | ||
peek_element_at_ring_buffer_index(self, element, *sizeStorage, i + sizeof(uint16_t)); | ||
} | ||
|
||
void tiny_queue_peek_partial(tiny_queue_t* self, void* element, uint16_t size, uint16_t element_index) | ||
{ | ||
uint16_t i = ring_buffer_index_for_element_index(self, element_index); | ||
peek_element_at_ring_buffer_index(self, element, size, i + sizeof(uint16_t)); | ||
} | ||
|
||
void tiny_queue_peek_size(tiny_queue_t* self, uint16_t* sizeStorage, uint16_t element_index) | ||
{ | ||
uint16_t i = ring_buffer_index_for_element_index(self, element_index); | ||
peek_element_size_at_ring_buffer_index(self, sizeStorage, i); | ||
} | ||
|
||
uint16_t tiny_queue_count(tiny_queue_t* self) | ||
{ | ||
return self->element_count; | ||
} | ||
|
||
void tiny_queue_init( | ||
tiny_queue_t* self, | ||
void* storage, | ||
size_t storageSize) | ||
{ | ||
self->element_count = 0; | ||
tiny_ring_buffer_init(&self->ring_buffer, storage, sizeof(uint8_t), storageSize); | ||
} |
Oops, something went wrong.