Skip to content

Instantly share code, notes, and snippets.

@yushijinhun
Created January 27, 2022 23:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yushijinhun/45fde239e511330bc8f9933eddc6987f to your computer and use it in GitHub Desktop.
Save yushijinhun/45fde239e511330bc8f9933eddc6987f to your computer and use it in GitHub Desktop.
Ring Buffer in C
#include "ring_buffer.h"
#include <string.h>
#include <sys/param.h>
void ringbuf_init(ringbuf_t *rb, uint8_t *buf, size_t buf_size) {
rb->buf = buf;
rb->size = buf_size;
rb->begin = rb->end = 0;
}
void ringbuf_reset(ringbuf_t *rb) {
rb->begin = rb->end = 0;
}
size_t ringbuf_bytes_used(const ringbuf_t *rb) {
if (rb->begin <= rb->end) {
return rb->end - rb->begin;
} else {
return rb->size - rb->begin + rb->end;
}
}
size_t ringbuf_bytes_free(const ringbuf_t *rb) {
if (rb->begin <= rb->end) {
return rb->size - rb->end + rb->begin - 1;
} else {
return rb->begin - rb->end - 1;
}
}
size_t ringbuf_capacity(const ringbuf_t *rb) {
return rb->size - 1;
}
size_t ringbuf_write(ringbuf_t *rb, const uint8_t *from, size_t n) {
size_t free_size = ringbuf_bytes_free(rb);
size_t overwritten = free_size >= n ? 0 : n - free_size;
size_t written;
while (n > 0) {
written = MIN(n, rb->size - rb->end);
memcpy(rb->buf + rb->end, from, written);
from += written;
n -= written;
rb->end += written;
if (rb->end == rb->size)
rb->end = 0;
}
if (overwritten > 0) {
if (rb->end == rb->size - 1)
rb->begin = 0;
else
rb->begin = rb->end + 1;
}
return overwritten;
}
size_t ringbuf_read(ringbuf_t *rb, uint8_t *to, size_t n) {
size_t available = ringbuf_bytes_used(rb);
size_t read;
if (rb->begin > rb->end) {
read = MIN(rb->size - rb->begin, n);
memcpy(to, rb->buf + rb->begin, read);
rb->begin += read;
if (rb->begin == rb->size)
rb->begin = 0;
if (read == n)
return read;
to += read;
n -= read;
}
read = MIN(rb->end - rb->begin, n);
memcpy(to, rb->buf + rb->begin, read);
rb->begin += read;
return MIN(available, n);
}
#pragma once
#include <stddef.h>
#include <stdint.h>
typedef struct {
uint8_t *buf;
size_t size;
size_t begin;
size_t end;
} ringbuf_t;
/**
* Initializes a ring buffer with a pre-allocated memory area.
* Capacity of the ring buffer = memory size - 1.
* @param rb the ring buffer to initialize
* @param buf the address of the pre-allocated memory
* @param buf_size the size of the memory, must be larger than 1
*/
void ringbuf_init(ringbuf_t *rb, uint8_t *buf, size_t buf_size);
/**
* Discards all data in the ring buffer.
*/
void ringbuf_reset(ringbuf_t *rb);
/**
* Calculates the used space size of the ring buffer.
*/
size_t ringbuf_bytes_used(const ringbuf_t *rb);
/**
* Calculates the free space size of the ring buffer.
*/
size_t ringbuf_bytes_free(const ringbuf_t *rb);
/**
* Gets the capacity of the ring buffer.
*/
size_t ringbuf_capacity(const ringbuf_t *rb);
/**
* Writes n bytes to the ring buffer.
* Old data will be overwritten if there is no enough space in the ring buffer.
* @returns the number of discarded bytes
*/
size_t ringbuf_write(ringbuf_t *rb, const uint8_t *from, size_t n);
/**
* Reads n bytes from the ring buffer.
* Fewer than n bytes is read if there is no enough data in the ring buffer.
* @returns the number of bytes read
*/
size_t ringbuf_read(ringbuf_t *rb, uint8_t *to, size_t n);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment