Skip to content

Instantly share code, notes, and snippets.

@jcoglan
Last active November 28, 2016 14:48
Show Gist options
  • Select an option

  • Save jcoglan/85614a39ce7929de1bdcac4acafefba3 to your computer and use it in GitHub Desktop.

Select an option

Save jcoglan/85614a39ce7929de1bdcac4acafefba3 to your computer and use it in GitHub Desktop.
#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;
}
@DanielMorsing
Copy link

also, welcome to C. The usual way of writing a function declaration that returns a pointer is foo* bar(). Yes, it makes no sense

@DRMacIver
Copy link

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