--- /dev/null
+/**
+ * © 2008 by David ‘Bombe’ Roden <bombe@pterodactylus.net>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "GrowingBuffer.h"
+
+GrowingBuffer::GrowingBuffer(size_t initialSize) {
+ this->data = malloc(1024);
+ this->size = 1024;
+ this->limit = 0;
+ this->position = 0;
+}
+
+GrowingBuffer::~GrowingBuffer() {
+ if (this->data) {
+ free(this->data);
+ }
+}
+
+size_t GrowingBuffer::getPosition() {
+ return position;
+}
+
+size_t GrowingBuffer::getLimit() {
+ return limit;
+}
+
+size_t GrowingBuffer::getSize() {
+ return size;
+}
+
+void GrowingBuffer::seek(size_t position) {
+ this->position = (position > limit) ? limit : position;
+}
+
+void* GrowingBuffer::read(void* buffer, size_t length) {
+ size_t bytesToCopy = (length > (limit - position)) ? (limit - position) : length;
+ memcpy(buffer, (char*) data + position, bytesToCopy);
+ position += bytesToCopy;
+ return buffer;
+}
+
+void GrowingBuffer::write(const void* buffer, size_t length) {
+ if (length > (size - position)) {
+ int newSize = size;
+ do {
+ newSize *= 2;
+ } while (length > (newSize - position));
+ void* newData = malloc(newSize);
+ memcpy(newData, data, position);
+ free(data);
+ data = newData;
+ }
+ memcpy((char*) data + position, buffer, length);
+}
+
+void GrowingBuffer::truncate() {
+ limit = position;
+}
+
+void GrowingBuffer::clear() {
+ position = 0;
+ limit = 0;
+}
+
+void GrowingBuffer::resize(double factor) {
+ if (factor < 1.0) {
+ factor = 1.0;
+ }
+ if (size != (limit * factor)) {
+ void* newData = malloc((size_t) (limit * factor));
+ memcpy(newData, data, limit);
+ free(data);
+ data = newData;
+ }
+}
+
--- /dev/null
+/**
+ * © 2008 by David ‘Bombe’ Roden <bombe@pterodactylus.net>
+ */
+
+#pragma once
+
+/**
+ * A buffer that will grow to accomodate the data being put into it.
+ */
+class GrowingBuffer {
+
+public:
+
+ /**
+ * Empty constructor. Creates a buffer with a default size of 1024 bytes.
+ *
+ * @param initialSize The initial size of the buffer in bytes
+ */
+ GrowingBuffer(size_t initialSize = 1024);
+
+ /**
+ * Destructor. Frees all used resources.
+ */
+ ~GrowingBuffer();
+
+ size_t getPosition();
+ size_t getLimit();
+ size_t getSize();
+
+ /**
+ * Sets the position of the buffer. The next {@link read(void*, size_t)} or
+ * {@link write(const void*, size_t)} operation will be applied at the new
+ * position.
+ *
+ * @param position The position to seek to
+ */
+ void seek(size_t position);
+ void* read(void* buffer, size_t length);
+ void write(const void* buffer, size_t length);
+ void truncate();
+ void clear();
+ void resize(double factor = 1.0);
+
+private:
+ void* data;
+ size_t size;
+ size_t limit;
+ size_t position;
+
+};
+