Skip to content

Instantly share code, notes, and snippets.

@icedraco
Created September 12, 2015 21:12
Show Gist options
  • Select an option

  • Save icedraco/d3f7609d500b3cc6f382 to your computer and use it in GitHub Desktop.

Select an option

Save icedraco/d3f7609d500b3cc6f382 to your computer and use it in GitHub Desktop.
Some circular buffer in C I felt like making once... :P
#include "buffer.h"
Buffer* buffer_create(int capacity) {
if (capacity <= 0)
return NULL;
Buffer* b = (Buffer*)malloc(sizeof(Buffer));
if (b) {
if (b->data = (char*)malloc(capacity * sizeof(char))) {
b->capacity = capacity;
b->currentSize = 0;
b->start = 0;
b->cursor = 0;
}
else {
free(b);
}
}
return b;
}
void buffer_free(Buffer* b) {
if (b) {
if (b->data)
free(b->data);
free(b);
}
}
int buffer_write(Buffer* b, const char* data, int n) {
int numBytes = 0;
int maxBytes = buffer_capacity(b) - buffer_size(b);
if (n < maxBytes)
maxBytes = n;
if (b) {
while (numBytes < maxBytes) {
b->data[b->cursor++] = data[numBytes++];
b->cursor %= b->capacity;
}
b->currentSize += numBytes;
}
return numBytes;
}
int buffer_read(Buffer* b, char* target, int n) {
int numBytes = buffer_copy(b, target, n);
b->start = (b->start + numBytes) % b->capacity;
b->currentSize -= numBytes;
return numBytes;
}
int buffer_copy(const Buffer* b, char* target, int n) {
int numBytes = 0;
int maxBytes = buffer_size(b);
int cursor;
if (n < maxBytes)
maxBytes = n;
if (b) {
cursor = b->start;
while (numBytes < maxBytes) {
target[numBytes++] = b->data[cursor++];
cursor %= b->capacity;
}
}
return numBytes;
}
int buffer_size(const Buffer* b) {
return b ? b->currentSize : 0;
}
int buffer_capacity(const Buffer* b) {
return b ? b->capacity : 0;
}
int buffer_isEmpty(const Buffer* b) {
return buffer_size(b) == 0;
}
int buffer_isFull(const Buffer* b) {
return buffer_size(b) == buffer_capacity(b);
}
#ifndef __BUFFER_H
#define __BUFFER_H
#include <stdlib.h>
typedef struct s_buffer {
int capacity;
int currentSize;
int cursor;
int start;
char* data;
} Buffer;
Buffer* buffer_create(int capacity);
/* Creates a new buffer with the given maximal capacity.
*/
void buffer_free(Buffer* b);
/* Frees/deallocates a previously created buffer.
*/
int buffer_write(Buffer* b, const char* data, int n);
/* Writes n bytes from data into the buffer.
* If n is bigger than the amount of free buffer space at the time,
* then the extra data will not be written.
*
* Returns the amount of bytes actually written.
*/
int buffer_read(Buffer* b, char* target, int n);
/* Reads up to n bytes from the buffer into target.
*
* Returns the amount of bytes actually read.
*/
int buffer_copy(const Buffer* b, char* target, int n);
/* Reads up to n bytes from the buffer into target.
* The data is not removed from the buffer, but merely copied, unlike
* buffer_read().
*
* Returns the amount of bytes actually copied.
*/
int buffer_size(const Buffer* b);
/* Returns the amount of bytes currently stored in the buffer.
* To see the buffer's maximal capacity, use buffer_capacity().
*/
int buffer_capacity(const Buffer* b);
/* Returns the maximal amount of bytes the buffer can contain at
* a time.
*/
int buffer_isEmpty(const Buffer* b);
/* Returns 1 if the buffer is empty or 0 otherwise.
*/
int buffer_isFull(const Buffer* b);
/* Returns 1 if the buffer is full or 0 otherwise.
*/
#endif
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "buffer.h"
#define BUFFER_SIZE 1000
#define TEST_STR "Stuff"
#define TEST_STR2 "IceDragon"
void test_capacity(int capacity) {
Buffer* b;
printf(" > Testing with capacity %d...\n", capacity);
b = buffer_create(capacity);
if (capacity <= 0) {
assert(b == 0);
assert(buffer_size(b) == 0);
assert(buffer_capacity(b) == 0);
assert(buffer_isEmpty(b));
assert(buffer_isFull(b));
}
else {
assert(b != 0);
assert(buffer_size(b) == 0);
assert(buffer_capacity(b) == capacity);
assert(buffer_isEmpty(b));
assert(!buffer_isFull(b));
}
buffer_free(b);
}
void test_regular_write(void) {
Buffer* b;
char buffer[BUFFER_SIZE];
int result;
printf(" > Testing regular write...\n");
b = buffer_create(BUFFER_SIZE);
// Write test string
result = buffer_write(b, TEST_STR, strlen(TEST_STR));
assert(result == strlen(TEST_STR));
assert(buffer_size(b) == strlen(TEST_STR));
assert(buffer_capacity(b) == BUFFER_SIZE);
assert(!buffer_isEmpty(b));
assert(!buffer_isFull(b));
// Write another after it
result = buffer_write(b, TEST_STR2, strlen(TEST_STR2));
assert(result == strlen(TEST_STR2));
assert(buffer_size(b) == strlen(TEST_STR) + strlen(TEST_STR2));
assert(buffer_capacity(b) == BUFFER_SIZE);
assert(!buffer_isEmpty(b));
assert(!buffer_isFull(b));
// Verify what was written
memset(buffer, 0, BUFFER_SIZE);
result = buffer_copy(b, buffer, BUFFER_SIZE);
assert(result == strlen(TEST_STR) + strlen(TEST_STR2));
assert(strncmp(buffer + 0, TEST_STR, strlen(TEST_STR)) == 0);
assert(strncmp(buffer + strlen(TEST_STR), TEST_STR2, strlen(TEST_STR2)) == 0);
assert(buffer_size(b) == strlen(TEST_STR) + strlen(TEST_STR2));
result = buffer_read(b, buffer, strlen(TEST_STR));
buffer[result] = '\0';
assert(result == strlen(TEST_STR));
assert(!strcmp(buffer, TEST_STR));
assert(buffer_size(b) == strlen(TEST_STR2));
result = buffer_read(b, buffer, strlen(TEST_STR2));
buffer[result] = '\0';
assert(result == strlen(TEST_STR2));
assert(!strcmp(buffer, TEST_STR2));
assert(buffer_size(b) == 0);
assert(buffer_isEmpty(b));
assert(!buffer_isFull(b));
}
int main(int argc, char** argv) {
printf("=== Buffer Tester ===============\n\n");
test_capacity(-1337);
test_capacity(0);
test_capacity(BUFFER_SIZE);
test_regular_write();
printf("\nDone all tests...\n\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment