blob: 52d41e1f46313e11cad5ef4cfc4a131202915ac3 [file] [log] [blame]
/*
* Copyright 2017, Data61, CSIRO (ABN 41 687 119 230)
*
* SPDX-License-Identifier: BSD-2-Clause
*/
/**
* @file circular_buffer.h
* @brief A circular buffer implementation
*/
#pragma once
#include <stdbool.h>
#include <sys/types.h>
#include <stdint.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <utils/zf_log.h>
/* Circular Buffer */
typedef struct circ_buf {
off_t head;
off_t tail;
size_t size;
uint8_t buf[];
} circ_buf_t;
static inline off_t _next_pos(circ_buf_t *cb, off_t pos)
{
return (pos + 1) % cb->size;
}
/**
* Initialise a new circular buffer
*
* @param size The size of the buffer in bytes.
* @param[in] cb Circular buffer structure allocated by the user.
*
* @return NULL on failure.
*/
static inline int circ_buf_init(size_t size, circ_buf_t *cb) {
if (size == 0 || !cb) {
ZF_LOGE("Invalid arguments\n");
return EINVAL;
}
cb->head = 0;
cb->tail = 0;
cb->size = size;
return 0;
}
/**
* Check if the circular buffer is full
*
* @param cb Circular buffer to check
*
* @return true indicates the buffer is full, false otherwise.
*/
static inline bool circ_buf_is_full(circ_buf_t *cb) {
return _next_pos(cb, cb->tail) == cb->head;
}
/**
* Check if the circular buffer is empty
*
* @param cb Circular buffer to check
*
* @return true indicates the buffer is empty, false otherwise.
*/
static inline bool circ_buf_is_empty(circ_buf_t *cb) {
return cb->tail == cb->head;
}
/**
* Put a byte
*
* @param cb Circular buffer to put via.
* @param c Byte to send.
*/
static inline void circ_buf_put(circ_buf_t *cb, uint8_t c) {
cb->buf[cb->tail] = c;
cb->tail = _next_pos(cb, cb->tail);
}
/**
* Get a byte
*
* @param cb Circular buffer to get from.
*
* @return The byte received.
*/
static inline uint8_t circ_buf_get(circ_buf_t *cb) {
uint8_t c = cb->buf[cb->head];
cb->head = _next_pos(cb, cb->head);
return c;
}