Last active
November 28, 2016 14:48
-
-
Save jcoglan/85614a39ce7929de1bdcac4acafefba3 to your computer and use it in GitHub Desktop.
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 <stdlib.h> | |
| #include <string.h> | |
| typedef char * BLOB; | |
| typedef struct BufferChunk { | |
| int length; | |
| int cursor; | |
| BLOB data; | |
| struct BufferChunk *next; | |
| } BufferChunk; | |
| typedef struct { | |
| int total; | |
| BufferChunk *head; | |
| } Buffer; | |
| BufferChunk *buffer_create_chunk() | |
| { | |
| BufferChunk *chunk = malloc(sizeof(BufferChunk)); | |
| chunk->length = 0; | |
| chunk->cursor = 0; | |
| chunk->data = NULL; | |
| chunk->next = NULL; | |
| return chunk; | |
| } | |
| Buffer *buffer_create() | |
| { | |
| Buffer *buf = malloc(sizeof(Buffer)); | |
| buf->total = 0; | |
| buf->head = buffer_create_chunk(); | |
| return buf; | |
| } | |
| void buffer_destroy(Buffer *buf) | |
| { | |
| // TODO free the remaining chain of chunks | |
| free(buf->head->data); | |
| free(buf->head); | |
| free(buf); | |
| } | |
| void buffer_push(Buffer *buf, int length, BLOB data) | |
| { | |
| buf->total += length; | |
| BufferChunk *chunk = buf->head; | |
| while (chunk->next != NULL) chunk = chunk->next; | |
| chunk->length = length; | |
| chunk->cursor = 0; | |
| chunk->data = malloc(sizeof(char) * length); | |
| memcpy(chunk->data, data, length); | |
| chunk->next = buffer_create_chunk(); | |
| } | |
| BLOB buffer_read(Buffer *buf, int length) | |
| { | |
| if (buf->total < length) return NULL; | |
| buf->total -= length; | |
| BufferChunk *chunk = buf->head; | |
| int offset = 0; | |
| BLOB result = malloc(sizeof(char) * length + 1); | |
| result[length] = '\0'; | |
| while (offset < length) { | |
| int size = chunk->length - chunk->cursor; | |
| int required = length - offset; | |
| int take = (required < size) ? required : size; | |
| memcpy(result + offset, chunk->data + chunk->cursor, take); | |
| offset += take; | |
| if (take >= size) { | |
| BufferChunk *old = chunk; | |
| chunk = chunk->next; | |
| free(old->data); | |
| free(old); | |
| } else { | |
| chunk->cursor += take; | |
| } | |
| } | |
| buf->head = chunk; | |
| return result; | |
| } | |
| BLOB buffer_read_all(Buffer *buf) | |
| { | |
| return buffer_read(buf, buf->total); | |
| } | |
| int main(int argc, char *argv[]) | |
| { | |
| Buffer *buf = buffer_create(); | |
| buffer_push(buf, 10, "The quick "); | |
| buffer_push(buf, 10, "brown fox "); | |
| buffer_push(buf, 15, "jumps over the "); | |
| buffer_push(buf, 9, "lazy dog."); | |
| int size = 12; | |
| while (buf->total >= size) { | |
| BLOB chunk = buffer_read(buf, size); | |
| printf("[%s]\n", chunk); | |
| free(chunk); | |
| } | |
| printf("[%s]\n", buffer_read_all(buf)); | |
| printf("%d\n", buf->total); | |
| buffer_destroy(buf); | |
| return 0; | |
| } |
also, welcome to C. The usual way of writing a function declaration that returns a pointer is foo* bar(). Yes, it makes no sense
Wait, really? That's totally not the style I've been using. Dammit.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
also, welcome to C. The usual way of writing a function declaration that returns a pointer is
foo* bar(). Yes, it makes no sense