Created
September 12, 2015 21:12
-
-
Save icedraco/d3f7609d500b3cc6f382 to your computer and use it in GitHub Desktop.
Some circular buffer in C I felt like making once... :P
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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