1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/core/lib/ringbuffer.c

150 lines
3.5 KiB
C
Raw Normal View History

2013-06-22 17:58:19 +02:00
/**
* Ringbuffer implementation
*
* Copyright (C) 2013 Freie Universität Berlin
* Copyright (C) 2013 INRIA
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
2013-06-22 17:58:19 +02:00
*
2014-11-16 11:31:57 +01:00
* @ingroup core_util
2013-06-22 17:58:19 +02:00
* @{
* @file
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author René Kijewski <rene.kijewski@fu-berlin.de>
2013-06-22 17:58:19 +02:00
* @}
*/
2013-10-10 17:06:14 +02:00
#include "ringbuffer.h"
2010-09-22 17:25:19 +02:00
#include <string.h>
2014-05-03 20:13:20 +02:00
/**
* @brief Add an element to the end of the ringbuffer.
* @details This helper function does not check the pre-requirements for adding,
* i.e. the caller has to ensure that ringbuffer_full() is false.
* @param[in,out] rb Ringbuffer to operate on.
* @param[in] c Element to add.
*/
static void add_tail(ringbuffer_t *restrict rb, char c)
{
unsigned pos = rb->start + rb->avail++;
2020-03-30 17:02:08 +02:00
if (pos >= rb->size) {
pos -= rb->size;
}
rb->buf[pos] = c;
}
2014-05-03 20:13:20 +02:00
/**
* @brief Remove an element from the start of the ringbuffer.
* @details This helper function does not check the pre-requirements for reading,
* i.e. the caller has to ensure that ringbuffer_empty() is false.
* @param[in,out] rb Ringbuffer to operate on.
* @returns The removed element.
*/
static char get_head(ringbuffer_t *restrict rb)
{
char result = rb->buf[rb->start];
2020-03-30 17:02:08 +02:00
if ((--rb->avail == 0) || (++rb->start == rb->size)) {
rb->start = 0;
}
return result;
}
unsigned ringbuffer_add(ringbuffer_t *restrict rb, const char *buf, unsigned n)
2013-06-22 17:58:19 +02:00
{
unsigned i;
2020-03-30 17:02:08 +02:00
for (i = 0; i < n; i++) {
if (ringbuffer_full(rb)) {
break;
}
add_tail(rb, buf[i]);
2010-09-24 13:53:22 +02:00
}
return i;
2010-09-24 13:53:22 +02:00
}
int ringbuffer_add_one(ringbuffer_t *restrict rb, char c)
2013-06-22 17:58:19 +02:00
{
int result = -1;
2020-03-30 17:02:08 +02:00
if (ringbuffer_full(rb)) {
2020-03-30 17:02:08 +02:00
result = (unsigned char)get_head(rb);
2013-06-22 17:58:19 +02:00
}
add_tail(rb, c);
return result;
2010-09-22 17:25:19 +02:00
}
int ringbuffer_get_one(ringbuffer_t *restrict rb)
2013-06-22 17:58:19 +02:00
{
if (!ringbuffer_empty(rb)) {
2020-03-30 17:02:08 +02:00
return (unsigned char)get_head(rb);
2013-06-22 17:58:19 +02:00
}
else {
return -1;
2013-06-22 17:58:19 +02:00
}
2010-09-22 17:25:19 +02:00
}
unsigned ringbuffer_get(ringbuffer_t *restrict rb, char *buf, unsigned n)
2013-06-22 17:58:19 +02:00
{
if (n > rb->avail) {
n = rb->avail;
2010-09-22 17:25:19 +02:00
}
if (n > 0) {
unsigned bytes_till_end = rb->size - rb->start;
if (bytes_till_end >= n) {
memcpy(buf, rb->buf + rb->start, n);
if (bytes_till_end == n) {
rb->start = 0;
}
else {
rb->start += n;
}
}
else {
memcpy(buf, rb->buf + rb->start, bytes_till_end);
rb->start = n - bytes_till_end;
memcpy(buf + bytes_till_end, rb->buf, rb->start);
}
rb->avail -= n;
}
return n;
2010-09-22 17:25:19 +02:00
}
unsigned ringbuffer_remove(ringbuffer_t *restrict rb, unsigned n)
{
if (n > rb->avail) {
n = rb->avail;
rb->start = rb->avail = 0;
}
else {
2017-03-01 22:01:26 +01:00
rb->start += n;
rb->avail -= n;
/* compensate underflow */
if (rb->start >= rb->size) {
2017-03-01 22:01:26 +01:00
rb->start -= rb->size;
}
}
return n;
}
int ringbuffer_peek_one(const ringbuffer_t *restrict rb_)
{
ringbuffer_t rb = *rb_;
2020-03-30 17:02:08 +02:00
return ringbuffer_get_one(&rb);
}
2020-03-30 17:02:08 +02:00
unsigned ringbuffer_peek(const ringbuffer_t *restrict rb_, char *buf,
unsigned n)
{
ringbuffer_t rb = *rb_;
2020-03-30 17:02:08 +02:00
return ringbuffer_get(&rb, buf, n);
}