1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/** 14 * @file circular_buffer.h 15 * @brief A circular buffer implementation 16 */ 17 18#pragma once 19 20#include <stdbool.h> 21#include <sys/types.h> 22#include <stdint.h> 23#include <unistd.h> 24#include <stdlib.h> 25#include <errno.h> 26 27#include <utils/zf_log.h> 28 29 30 31/* Circular Buffer */ 32typedef struct circ_buf { 33 off_t head; 34 off_t tail; 35 size_t size; 36 uint8_t buf[]; 37} circ_buf_t; 38 39 40static inline off_t _next_pos(circ_buf_t *cb, off_t pos) 41{ 42 return (pos + 1) % cb->size; 43} 44 45 46/** 47 * Initialise a new circular buffer 48 * 49 * @param size The size of the buffer in bytes. 50 * @param[in] cb Circular buffer structure allocated by the user. 51 * 52 * @return NULL on failure. 53 */ 54static inline int circ_buf_init(size_t size, circ_buf_t *cb) { 55 if (size == 0 || !cb) { 56 ZF_LOGE("Invalid arguments\n"); 57 return EINVAL; 58 } 59 60 cb->head = 0; 61 cb->tail = 0; 62 cb->size = size; 63 64 return 0; 65} 66 67/** 68 * Check if the circular buffer is full 69 * 70 * @param cb Circular buffer to check 71 * 72 * @return true indicates the buffer is full, false otherwise. 73 */ 74static inline bool circ_buf_is_full(circ_buf_t *cb) { 75 return _next_pos(cb, cb->tail) == cb->head; 76} 77 78/** 79 * Check if the circular buffer is empty 80 * 81 * @param cb Circular buffer to check 82 * 83 * @return true indicates the buffer is empty, false otherwise. 84 */ 85static inline bool circ_buf_is_empty(circ_buf_t *cb) { 86 return cb->tail == cb->head; 87} 88 89/** 90 * Put a byte 91 * 92 * @param cb Circular buffer to put via. 93 * @param c Byte to send. 94 */ 95static inline void circ_buf_put(circ_buf_t *cb, uint8_t c) { 96 cb->buf[cb->tail] = c; 97 cb->tail = _next_pos(cb, cb->tail); 98} 99 100/** 101 * Get a byte 102 * 103 * @param cb Circular buffer to get from. 104 * 105 * @return The byte received. 106 */ 107static inline uint8_t circ_buf_get(circ_buf_t *cb) { 108 uint8_t c = cb->buf[cb->head]; 109 cb->head = _next_pos(cb, cb->head); 110 111 return c; 112} 113 114