224 lines
5.1 KiB
C

/*!
* \file deque08.c
* \brief
* This file provides double ended queue capability based on a ring buffer
*
* Copyright (C) 2014 Houtouridis Christos <houtouridis.ch@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "deque08.h"
/*
* ============= Private Queue API =============
*/
static iterator_t _preInc(deque08_t *q, iterator_t* it) {
return (++*it >= q->capacity) ? *it=0 : *it;
}
static iterator_t _preDec(deque08_t *q, iterator_t* it) {
return (--*it < 0) ? *it=q->capacity-1 : *it;
}
static iterator_t _postInc(deque08_t *q, iterator_t* it) {
iterator_t ret = *it;
if (++*it >= q->capacity) *it=0;
return ret;
}
static iterator_t _postDec(deque08_t *q, iterator_t* it) {
iterator_t ret = *it;
if (--*it < 0) *it=q->capacity-1;
return ret;
}
/*
* ============= Public Queue API =============
*/
/*
* Link and Glue functions
*/
void deque08_link_buffer (deque08_t *q, byte_t* buf) {
q->m = buf;
}
/*
* Set functions
*/
inline void deque08_set_capacity (deque08_t *q, size_t capacity) {
q->capacity = capacity;
}
/*
* User Functions
*/
/*!
* \brief
* Check if deque is full
* \param q Which deque to check
* \return
* \arg 0 Not full
* \arg 1 Full
*/
int deque08_is_full (deque08_t *q) {
return (q->items == q->capacity) ? 1:0;
}
/*!
* \brief
* Check if deque is empty
* \param q Which deque to check
* \return
* \arg 0 Not empty
* \arg 1 Empty
*/
int deque08_is_empty (deque08_t *q) {
return (q->items) ? 0:1;
}
/*!
* \brief
* Return the number of items on deque
* \param q Which deque to check
*/
int deque08_size (deque08_t *q) {
return q->items;
}
/*!
* \brief
* Discard all items in deque
* \param q Which deque to check
*/
void deque08_flush (deque08_t *q) {
deque08_init(q);
}
/*!
* \brief
* Initialize the queue
* \param queue Which queue to init
*/
void deque08_init (deque08_t *q) {
q->f = 0;
q->r = -1;
q->items =0;
}
/*!
* \brief
* This function push a byte in front of deque.
* \param q Pointer to deque to use
* \param b byte to push
* \return
* \arg 0 Full queue
* \arg 1 Done
*/
int deque08_push_front (deque08_t *q, byte_t b) {
if (deque08_is_full (q) == 1) //full queue
return 0;
q->m [_preDec (q, &q->f)] = b;
++q->items;
return 1;
}
/*!
* \brief
* This function pops a byte from the front of the deque.
* \param q Pointer to deque to use
* \param b Pointer to byte to return
* \return
* \arg 0 Empty queue
* \arg 1 Done
*/
int deque08_pop_front (deque08_t *q, byte_t *b) {
if (deque08_is_empty (q) == 1) //empty queue
return 0;
*b = q->m [_postInc (q, &q->f)];
--q->items;
return 1;
}
/*!
* \brief
* This function push a byte in the back of deque.
* \param q Pointer to deque to use
* \param b byte to push
* \return
* \arg 0 Full queue
* \arg 1 Done
*/
int deque08_push_back (deque08_t *q, byte_t b) {
if (deque08_is_full (q) == 1) //full queue
return 0;
q->m [_preInc (q, &q->r)] = b;
++q->items;
return 1;
}
/*!
* \brief
* This function pops a byte from the back of the deque.
* \param q Pointer to deque to use
* \param b Pointer to byte to return
* \return
* \arg 0 Empty queue
* \arg 1 Done
*/
int deque08_pop_back (deque08_t *q, byte_t *b) {
if (deque08_is_empty (q) == 1) //empty queue
return 0;
*b = q->m [_postDec (q, &q->r)];
--q->items;
return 1;
}
/*!
* \brief
* This function gives the last item in the back of deque.
* \param q Pointer to deque to use
* \param b Pointer to byte to return
* \return
* \arg 0 Empty queue
* \arg 1 Done
*/
int deque08_back (deque08_t *q, byte_t *b) {
if (deque08_is_empty (q) == 1) //empty queue
return 0;
*b = q->m [q->r];
return 1;
}
/*!
* \brief
* This function gives the first item in the front of deque.
* \param q Pointer to deque to use
* \param b Pointer to byte to return
* \return
* \arg 0 Empty queue
* \arg 1 Done
*/
int deque08_front (deque08_t *q, byte_t *b) {
if (deque08_is_empty (q) == 1) //empty queue
return 0;
*b = q->m [q->f];
return 1;
}