Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions c/includes/circular_buffer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef CIRCULAR_BUFFER_H
#define CIRCULAR_BUFFER_H
#include <stddef.h>

typedef struct CircularBuffer CircularBuffer;

CircularBuffer* cb_new(size_t capacity);
short cb_enqueue(CircularBuffer* buffer, const void* item);
void* cb_dequeue(CircularBuffer* buffer);
short cb_empty(CircularBuffer* buffer);
short cb_full(CircularBuffer* buffer);
void cb_free(CircularBuffer* buffer);

#endif // CIRCULAR_BUFFER_H
9 changes: 9 additions & 0 deletions c/src/queue/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("@rules_cc//cc:defs.bzl", "cc_library")

cc_library(
name = "circular_buffer",
srcs = ["circular_buffer.c"],
hdrs = ["//c/includes:circular_buffer.h"],
strip_include_prefix = "//c",
visibility = ["//visibility:public"],
)
56 changes: 56 additions & 0 deletions c/src/queue/circular_buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "includes/circular_buffer.h"

#include <stdlib.h>

struct CircularBuffer {
void** data;
size_t capacity;
size_t size;
size_t head;
size_t tail;
};

CircularBuffer* cb_new(size_t capacity) {
CircularBuffer* buffer = malloc(sizeof(CircularBuffer));
if (buffer == NULL) return NULL;

buffer->data = calloc(capacity, sizeof(void*));
if (buffer->data == NULL) {
free(buffer);
return NULL;
}

buffer->capacity = capacity;
buffer->size = 0;
buffer->head = 0;
buffer->tail = 0;

return buffer;
}

short cb_empty(CircularBuffer* buffer) { return buffer->size == 0; }

short cb_full(CircularBuffer* buffer) { return buffer->size == buffer->capacity; }

short cb_enqueue(CircularBuffer* buffer, const void* item) {
if (cb_full(buffer)) return -1;

buffer->data[buffer->tail] = (void*)item;
buffer->tail = (buffer->tail + 1) % buffer->capacity;
buffer->size++;
return 0;
}

void* cb_dequeue(CircularBuffer* buffer) {
if (cb_empty(buffer)) return NULL;

void** item = buffer->data[buffer->head];
buffer->head = (buffer->head + 1) % buffer->capacity;
buffer->size--;
return item;
}

void cb_free(CircularBuffer* buffer) {
free(buffer->data);
free(buffer);
}
1 change: 1 addition & 0 deletions c/tests/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ cc_test(
"//c/src/linkedlist:slinkedlist",
"//c/src/stack:llstack",
"//c/src/stack:arrstack",
"//c/src/queue:circular_buffer",
"@googletest//:gtest_main",
],
)
55 changes: 55 additions & 0 deletions c/tests/circular_buffer_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "gtest/gtest.h"

extern "C" {
#include "includes/circular_buffer.h"
}

TEST(CircularBufferTest, NewCircularBuffer) {
CircularBuffer* buffer = cb_new(10);
ASSERT_NE(buffer, nullptr);
ASSERT_EQ(cb_empty(buffer), 1);
ASSERT_EQ(cb_full(buffer), 0);
cb_free(buffer);
}

TEST(CircularBufferTest, EnqueueAndDequeue) {
CircularBuffer* buffer = cb_new(10);
ASSERT_NE(buffer, nullptr);
ASSERT_EQ(cb_empty(buffer), 1);
ASSERT_EQ(cb_full(buffer), 0);
int item1 = 10;
int item2 = 20;
int item3 = 30;
ASSERT_EQ(cb_enqueue(buffer, &item1), 0);
ASSERT_EQ(cb_enqueue(buffer, &item2), 0);
ASSERT_EQ(cb_enqueue(buffer, &item3), 0);
ASSERT_EQ(cb_empty(buffer), 0);
ASSERT_EQ(cb_full(buffer), 0);
ASSERT_EQ(cb_dequeue(buffer), &item1);
ASSERT_EQ(cb_empty(buffer), 0);
ASSERT_EQ(cb_full(buffer), 0);
ASSERT_EQ(cb_dequeue(buffer), &item2);
ASSERT_EQ(cb_empty(buffer), 0);
ASSERT_EQ(cb_full(buffer), 0);
ASSERT_EQ(cb_dequeue(buffer), &item3);
ASSERT_EQ(cb_empty(buffer), 1);
ASSERT_EQ(cb_full(buffer), 0);
cb_free(buffer);
}

TEST(CircularBufferTest, EnqueueAndDequeueWithOverflow) {
CircularBuffer* buffer = cb_new(3);
ASSERT_NE(buffer, nullptr);
ASSERT_EQ(cb_empty(buffer), 1);
ASSERT_EQ(cb_full(buffer), 0);
int item1 = 10;
int item2 = 20;
int item3 = 30;
int item4 = 40;
ASSERT_EQ(cb_enqueue(buffer, &item1), 0);
ASSERT_EQ(cb_enqueue(buffer, &item2), 0);
ASSERT_EQ(cb_enqueue(buffer, &item3), 0);
ASSERT_EQ(cb_enqueue(buffer, &item4), -1);

cb_free(buffer);
}
Loading