Files
MentOS/libc/inc/ring_buffer.h
T
Enrico Fraccaroli (Galfurian) 30e01ba560 Update version
2024-01-17 13:49:48 +01:00

128 lines
9.8 KiB
C

/// @file ring_buffer.h
/// @brief
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
/// @brief Declares a fixed-size ring-buffer.
#define DECLARE_FIXED_SIZE_RING_BUFFER(type, name, length, init) \
typedef struct fs_rb_##name##_t { \
unsigned size, read, write; \
type buffer[length]; \
} fs_rb_##name##_t; \
static inline void fs_rb_##name##_init(fs_rb_##name##_t *rb) \
{ \
rb->size = length; \
rb->read = rb->write = 0; \
char *dst = (char *)rb->buffer; \
long num = sizeof(type) * length; \
while (num--) *dst++ = (char)(init & 0xFF); \
} \
static inline unsigned fs_rb_##name##_step(fs_rb_##name##_t *rb, unsigned index) \
{ \
return (index == (rb->size - 1)) ? 0 : index + 1; \
} \
static inline void fs_rb_##name##_push_front(fs_rb_##name##_t *rb, type item) \
{ \
if (fs_rb_##name##_step(rb, rb->write) == rb->read) \
rb->read = fs_rb_##name##_step(rb, rb->read); \
rb->buffer[rb->write] = item; \
rb->write = fs_rb_##name##_step(rb, rb->write); \
} \
static inline type fs_rb_##name##_empty(fs_rb_##name##_t *rb) \
{ \
return rb->write == rb->read; \
} \
static inline type fs_rb_##name##_pop_back(fs_rb_##name##_t *rb) \
{ \
type item = init; \
if (!fs_rb_##name##_empty(rb)) { \
item = rb->buffer[rb->read]; \
rb->read = fs_rb_##name##_step(rb, rb->read); \
} \
return item; \
} \
static inline type fs_rb_##name##_pop_front(fs_rb_##name##_t *rb) \
{ \
if (fs_rb_##name##_empty(rb)) \
return init; \
rb->write = (rb->write > 0) ? rb->write - 1 : rb->size - 1; \
return rb->buffer[rb->write]; \
} \
static inline type fs_rb_##name##_get(fs_rb_##name##_t *rb, unsigned index) \
{ \
if (index < rb->size) \
return rb->buffer[index]; \
return init; \
} \
static inline type fs_rb_##name##_back(fs_rb_##name##_t *rb) \
{ \
if (fs_rb_##name##_empty(rb)) \
return init; \
return rb->buffer[rb->read]; \
} \
static inline type fs_rb_##name##_front(fs_rb_##name##_t *rb) \
{ \
if (fs_rb_##name##_empty(rb)) \
return init; \
return rb->buffer[(rb->write > 0) ? rb->write - 1 : rb->size - 1]; \
}
#ifdef __KERNEL__
/// Function for allocating memory for the ring buffer.
#define RING_BUFFER_ALLOC kmalloc
/// Function for freeing the memory for the ring buffer.
#define RING_BUFFER_FREE kfree
#else
/// Function for allocating memory for the ring buffer.
#define RING_BUFFER_ALLOC malloc
/// Function for freeing the memory for the ring buffer.
#define RING_BUFFER_FREE free
#endif
/// @brief Declares a dynamic-size ring-buffer.
#define DECLARE_RING_BUFFER(type, name, init) \
typedef struct rb_##name##_t { \
const unsigned size; \
unsigned read, write; \
type *buffer; \
} rb_##name##_t; \
static inline rb_##name##_t alloc_rb_##name(unsigned len) \
{ \
rb_##name##_t rb = { len, 0U, 0U, len > 0 ? RING_BUFFER_ALLOC(sizeof(type) * len) : NULL }; \
memset(rb.buffer, init, sizeof(type) * len); \
return rb; \
} \
static inline void free_rb_##name(rb_##name##_t *rb) \
{ \
RING_BUFFER_FREE(rb->buffer); \
} \
static inline unsigned step_rb_##name(rb_##name##_t *rb, unsigned index) \
{ \
return (index == (rb->size - 1)) ? 0 : index + 1; \
} \
static inline void push_rb_##name(rb_##name##_t *rb, type item) \
{ \
if (step_rb_##name(rb, rb->write) == rb->read) \
rb->read = step_rb_##name(rb, rb->read); \
rb->buffer[rb->write] = item; \
rb->write = step_rb_##name(rb, rb->write); \
} \
static inline void pop_rb_##name(rb_##name##_t *rb, type *item) \
{ \
*item = init; \
if (rb->write != rb->read) { \
*item = rb->buffer[rb->read]; \
rb->read = step_rb_##name(rb, rb->read); \
} \
} \
static inline void get_rb_##name(rb_##name##_t *rb, unsigned index, type *item) \
{ \
if (index < rb->size) \
*item = rb->buffer[index]; \
}
#undef RING_BUFFER_ALLOC
#undef RING_BUFFER_FREE