Skip to content

Commit

Permalink
v2.0:
Browse files Browse the repository at this point in the history
- No more inlines in header file (to generate proper static library)
- MISRA refactoring
  • Loading branch information
SMFSW committed Apr 16, 2024
1 parent 7129334 commit 16038a7
Show file tree
Hide file tree
Showing 7 changed files with 670 additions and 308 deletions.
293 changes: 207 additions & 86 deletions Doxyfile

Large diffs are not rendered by default.

293 changes: 207 additions & 86 deletions Doxyfile.auto

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BSD 3-Clause License

Copyright (c) 2017-2023, SMFSW
Copyright (c) 2017-2024, SMFSW
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
6 changes: 5 additions & 1 deletion ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cQueue: Queue handling library (written in plain c)
2017-2023 SMFSW
2017-2024 SMFSW

Feel free to share your thoughts @ xgarmanboziax@gmail.com about:
- issues encountered
Expand All @@ -10,6 +10,10 @@ Feel free to share your thoughts @ xgarmanboziax@gmail.com about:

** Actual:

v2.0: 15 Apr 2024:
- No more inlines in header file (to generate proper static library)
- MISRA refactoring

v1.9: 13 Sep 2023:
- Fixed stddef.h missing include for some toolchains, thanks to @Junbo-Zheng

Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=cQueue
version=1.9
version=2.0
author=SMFSW <xgarmanboziax@gmail.com>
maintainer=SMFSW <xgarmanboziax@gmail.com>
sentence=Queue handling library (written in plain c)
Expand Down
259 changes: 189 additions & 70 deletions src/cQueue.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*!\file cQueue.c
** \author SMFSW
** \copyright BSD 3-Clause License (c) 2017-2023, SMFSW
** \copyright BSD 3-Clause License (c) 2017-2024, SMFSW
** \brief Queue handling library (written in plain c)
** \details Queue handling library (written in plain c)
**/
Expand All @@ -12,16 +12,22 @@
/****************************************************************/


#define QUEUE_INITIALIZED 0x5AA5U //!< Initialized queue control value


/**************************/
/*** INTERNAL FUNCTIONS ***/
/**************************/
/*! \brief Increment index
** \details Increment buffer index \b pIdx rolling back to \b start when limit \b end is reached
** \param [in,out] pIdx - pointer to index value
** \param [in] end - counter upper limit value
** \param [in] start - counter lower limit value
**/
static inline void __attribute__((nonnull, always_inline)) inc_idx(uint16_t * const pIdx, const uint16_t end, const uint16_t start)
static inline void __attribute__((nonnull, always_inline)) _inc_idx(uint16_t * const pIdx, const uint16_t end, const uint16_t start)
{
if (*pIdx < end - 1) { (*pIdx)++; }
else { *pIdx = start; }
if (*pIdx < (end - 1U)) { (*pIdx)++; }
else { *pIdx = start; }
}

/*! \brief Decrement index
Expand All @@ -30,20 +36,59 @@ static inline void __attribute__((nonnull, always_inline)) inc_idx(uint16_t * co
** \param [in] end - counter upper limit value
** \param [in] start - counter lower limit value
**/
static inline void __attribute__((nonnull, always_inline)) dec_idx(uint16_t * const pIdx, const uint16_t end, const uint16_t start)
static inline void __attribute__((nonnull, always_inline)) _dec_idx(uint16_t * const pIdx, const uint16_t end, const uint16_t start)
{
if (*pIdx > start) { (*pIdx)--; }
else { *pIdx = end - 1; }
else { *pIdx = end - 1U; }
}


/*! \brief get initialization state of the queue
** \param [in] pQ - pointer of queue to handle
** \return Queue initialization status
** \retval true if queue is allocated
** \retval false is queue is not allocated
**/
static inline bool __attribute__((nonnull, always_inline)) _q_isInitialized(const Queue_t * const pQ) {
return (pQ->init == QUEUE_INITIALIZED) ? true : false; }

/*! \brief get emptiness state of the queue
** \param [in] pQ - pointer of queue to handle
** \return Queue emptiness status
** \retval true if queue is empty
** \retval false is not empty
**/
static inline bool __attribute__((nonnull, always_inline)) _q_isEmpty(const Queue_t * const pQ) {
return (pQ->cnt == 0U) ? true : false; }

/*! \brief get fullness state of the queue
** \param [in] pQ - pointer of queue to handle
** \return Queue fullness status
** \retval true if queue is full
** \retval false is not full
**/
static inline bool __attribute__((nonnull, always_inline)) _q_isFull(const Queue_t * const pQ) {
return (pQ->cnt == pQ->rec_nb) ? true : false; }


/*! \brief get number of records in the queue
** \param [in] pQ - pointer of queue to handle
** \return Number of records stored in the queue
**/
static inline uint16_t __attribute__((nonnull, always_inline)) _q_getCount(const Queue_t * const pQ) {
return pQ->cnt; }


/************************/
/*** PUBLIC FUNCTIONS ***/
/************************/
void * __attribute__((nonnull)) q_init( Queue_t * const pQ,
const size_t size_rec, const uint16_t nb_recs,
const QueueType type, const bool overwrite)
{
q_kill(pQ); // De-Init queue (if previously initialized) and set structure to 0 to ensure proper functions behavior when queue is not allocated

const uint32_t size = nb_recs * size_rec;
const size_t size = nb_recs * size_rec;

pQ->queue = (uint8_t *) malloc(size);

Expand All @@ -63,21 +108,18 @@ void * __attribute__((nonnull)) q_init( Queue_t * const pQ,
return pQ->queue; // return NULL when queue not properly allocated, Queue data address otherwise
}

void * __attribute__((nonnull)) q_init_static( Queue_t * const pQ,
const size_t size_rec, const uint16_t nb_recs,
const QueueType type, const bool overwrite,
void * const pQDat, const size_t lenQDat)
void * __attribute__((nonnull(1))) q_init_static( Queue_t * const pQ,
const size_t size_rec, const uint16_t nb_recs,
const QueueType type, const bool overwrite,
void * const pQDat, const size_t lenQDat)
{
q_kill(pQ); // De-Init queue (if previously initialized) and set structure to 0 to ensure proper functions behavior when queue is not allocated

const uint32_t size = nb_recs * size_rec;

if (lenQDat < size) { return NULL; } // Check static Queue data size

pQ->queue = (uint8_t *) pQDat;
const size_t size = nb_recs * size_rec;

if (pQ->queue != NULL)
if ((pQDat != NULL) && (lenQDat >= size)) // Check static Queue pointer and data size
{
pQ->queue = (uint8_t *) pQDat;
pQ->queue_sz = size;
pQ->rec_sz = size_rec;
pQ->rec_nb = nb_recs;
Expand All @@ -92,7 +134,7 @@ void * __attribute__((nonnull)) q_init_static( Queue_t * const pQ,

void __attribute__((nonnull)) q_kill(Queue_t * const pQ)
{
if ((pQ->init == QUEUE_INITIALIZED) && pQ->dynamic && (pQ->queue != NULL)) { free(pQ->queue); } // Free existing data (if already dynamically initialized)
if (_q_isInitialized(pQ) && pQ->dynamic && (pQ->queue != NULL)) { free(pQ->queue); } // Free existing data (if already dynamically initialized)
memset(pQ, 0, sizeof(Queue_t));
}

Expand All @@ -107,98 +149,175 @@ void __attribute__((nonnull)) q_flush(Queue_t * const pQ)

bool __attribute__((nonnull)) q_push(Queue_t * const pQ, const void * const record)
{
if ((!pQ->ovw) && q_isFull(pQ)) { return false; }

uint8_t * const pStart = pQ->queue + (pQ->rec_sz * pQ->in);
memcpy(pStart, record, pQ->rec_sz);
bool ret = true;

inc_idx(&pQ->in, pQ->rec_nb, 0);
if (_q_isFull(pQ)) // No more records available
{
if (pQ->ovw) // Queue is full, overwrite is allowed
{
if (pQ->impl == FIFO)
{
_inc_idx(&pQ->out, pQ->rec_nb, 0); // as oldest record is overwritten, increment out
}
//else if (pQ->impl == LIFO) {} // Nothing to do in this case
}
else
{
ret = false;
}
}
else
{
pQ->cnt++; // Increase records count
}

if (!q_isFull(pQ)) { pQ->cnt++; } // Increase records count
else if (pQ->ovw) // Queue is full and overwrite is allowed
if (ret)
{
if (pQ->impl == FIFO) { inc_idx(&pQ->out, pQ->rec_nb, 0); } // as oldest record is overwritten, increment out
//else if (pQ->impl == LIFO) {} // Nothing to do in this case
uint8_t * const pStart = pQ->queue + (pQ->rec_sz * pQ->in);
memcpy(pStart, record, pQ->rec_sz);
_inc_idx(&pQ->in, pQ->rec_nb, 0);
}

return true;
return ret;
}

bool __attribute__((nonnull)) q_pop(Queue_t * const pQ, void * const record)
{
const uint8_t * pStart;
bool ret = true;

if (q_isEmpty(pQ)) { return false; } // No more records

if (pQ->impl == FIFO)
if (_q_isEmpty(pQ)) // No records
{
pStart = pQ->queue + (pQ->rec_sz * pQ->out);
inc_idx(&pQ->out, pQ->rec_nb, 0);
ret = false;
}
else if (pQ->impl == LIFO)
else
{
dec_idx(&pQ->in, pQ->rec_nb, 0);
pStart = pQ->queue + (pQ->rec_sz * pQ->in);
const uint8_t * pStart;

if (pQ->impl == FIFO)
{
pStart = pQ->queue + (pQ->rec_sz * pQ->out);
_inc_idx(&pQ->out, pQ->rec_nb, 0);
}
else /* if (pQ->impl == LIFO) */
{
_dec_idx(&pQ->in, pQ->rec_nb, 0);
pStart = pQ->queue + (pQ->rec_sz * pQ->in);
}

memcpy(record, pStart, pQ->rec_sz);
pQ->cnt--; // Decrease records count
}
else { return false; }

memcpy(record, pStart, pQ->rec_sz);
pQ->cnt--; // Decrease records count
return true;
return ret;
}

bool __attribute__((nonnull)) q_peek(const Queue_t * const pQ, void * const record)
{
const uint8_t * pStart;

if (q_isEmpty(pQ)) { return false; } // No more records
bool ret = true;

if (pQ->impl == FIFO)
if (_q_isEmpty(pQ)) // No records
{
pStart = pQ->queue + (pQ->rec_sz * pQ->out);
// No change on out var as it's just a peek
ret = false;
}
else if (pQ->impl == LIFO)
else
{
uint16_t rec = pQ->in; // Temporary var for peek (no change on pQ->in with dec_idx)
dec_idx(&rec, pQ->rec_nb, 0);
pStart = pQ->queue + (pQ->rec_sz * rec);
const uint8_t * pStart;

if (pQ->impl == FIFO)
{
pStart = pQ->queue + (pQ->rec_sz * pQ->out);
// No change on out var as it's just a peek
}
else /* if (pQ->impl == LIFO) */
{
uint16_t rec = pQ->in; // Temporary var for peek (no change on pQ->in with dec_idx)
_dec_idx(&rec, pQ->rec_nb, 0);
pStart = pQ->queue + (pQ->rec_sz * rec);
}

memcpy(record, pStart, pQ->rec_sz);
}
else { return false; }

memcpy(record, pStart, pQ->rec_sz);
return true;
return ret;
}

bool __attribute__((nonnull)) q_drop(Queue_t * const pQ)
{
if (q_isEmpty(pQ)) { return false; } // No more records
bool ret = true;

if (pQ->impl == FIFO) { inc_idx(&pQ->out, pQ->rec_nb, 0); }
else if (pQ->impl == LIFO) { dec_idx(&pQ->in, pQ->rec_nb, 0); }
else { return false; }
if (_q_isEmpty(pQ)) // No records
{
ret = false;
}
else
{
if (pQ->impl == FIFO)
{
_inc_idx(&pQ->out, pQ->rec_nb, 0);
}
else /*if (pQ->impl == LIFO)*/
{
_dec_idx(&pQ->in, pQ->rec_nb, 0);
}

pQ->cnt--; // Decrease records count
}

pQ->cnt--; // Decrease records count
return true;
return ret;
}

bool __attribute__((nonnull)) q_peekIdx(const Queue_t * const pQ, void * const record, const uint16_t idx)
{
const uint8_t * pStart;

if (idx + 1 > q_getCount(pQ)) { return false; } // Index out of range
bool ret = true;

if (pQ->impl == FIFO)
if ((idx + 1U) > _q_getCount(pQ)) // Index out of range
{
pStart = pQ->queue + (pQ->rec_sz * ((pQ->out + idx) % pQ->rec_nb));
ret = false;
}
else if (pQ->impl == LIFO)
else
{
pStart = pQ->queue + (pQ->rec_sz * idx);
const uint8_t * pStart;

if (pQ->impl == FIFO)
{
pStart = pQ->queue + (pQ->rec_sz * ((pQ->out + idx) % pQ->rec_nb));
}
else /* if (pQ->impl == LIFO) */
{
pStart = pQ->queue + (pQ->rec_sz * idx);
}

memcpy(record, pStart, pQ->rec_sz);
}
else { return false; }

memcpy(record, pStart, pQ->rec_sz);
return true;
return ret;
}

bool __attribute__((nonnull)) q_peekPrevious(const Queue_t * const pQ, void * const record)
{
const uint16_t idx = _q_getCount(pQ) - 1U; // No worry about count -1 when queue is empty, test is done by q_peekIdx
return q_peekIdx(pQ, record, idx);
}


/**********************/
/*** PUBLIC GETTERS ***/
/**********************/
bool __attribute__((nonnull)) q_isInitialized(const Queue_t * const pQ) {
return _q_isInitialized(pQ); }

uint32_t __attribute__((nonnull)) q_sizeof(const Queue_t * const pQ) {
return pQ->queue_sz; }

bool __attribute__((nonnull)) q_isEmpty(const Queue_t * const pQ) {
return _q_isEmpty(pQ); }

bool __attribute__((nonnull)) q_isFull(const Queue_t * const pQ) {
return _q_isFull(pQ); }

uint16_t __attribute__((nonnull)) q_getCount(const Queue_t * const pQ) {
return _q_getCount(pQ); }

uint16_t __attribute__((nonnull)) q_getRemainingCount(const Queue_t * const pQ) {
return pQ->rec_nb - pQ->cnt; }

Loading

0 comments on commit 16038a7

Please sign in to comment.