summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--includes/Buffer.h24
-rw-r--r--src/Buffer.cc76
-rw-r--r--tests/test-Handles.cc12
4 files changed, 113 insertions, 0 deletions
diff --git a/Makefile b/Makefile
index 6fd9f18..fabb147 100644
--- a/Makefile
+++ b/Makefile
@@ -121,6 +121,7 @@ Handle.cc \
Input.cc \
Output.cc \
Socket.cc \
+Buffer.cc \
\
Task.cc \
TaskMan.cc \
diff --git a/includes/Buffer.h b/includes/Buffer.h
new file mode 100644
index 0000000..99a57f0
--- /dev/null
+++ b/includes/Buffer.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <Handle.h>
+
+namespace Balau {
+
+class Buffer : public SeekableHandle {
+ public:
+ Buffer() throw (GeneralException) : m_buffer(NULL), m_bufSize(0), m_numBlocks(0) { }
+ virtual void close() throw (GeneralException);
+ virtual ssize_t read(void * buf, size_t count) throw (GeneralException);
+ virtual ssize_t write(const void * buf, size_t count) throw (GeneralException);
+ virtual bool isClosed();
+ virtual bool canRead();
+ virtual bool canWrite();
+ virtual const char * getName();
+ virtual off_t getSize();
+ void reset();
+ private:
+ uint8_t * m_buffer;
+ off_t m_bufSize, m_numBlocks;
+};
+
+};
diff --git a/src/Buffer.cc b/src/Buffer.cc
new file mode 100644
index 0000000..d6ff9bb
--- /dev/null
+++ b/src/Buffer.cc
@@ -0,0 +1,76 @@
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "Buffer.h"
+#include "Task.h"
+#include "Printer.h"
+
+static const int s_blockSize = 16 * 1024;
+
+void Balau::Buffer::close() throw (GeneralException) {
+ reset();
+}
+
+ssize_t Balau::Buffer::read(void * buf, size_t count) throw (GeneralException) {
+ off_t cursor = rtell();
+ if (cursor >= m_bufSize)
+ return 0;
+ off_t avail = m_bufSize - cursor;
+
+ if (count > avail)
+ count = avail;
+
+ memcpy(buf, m_buffer + cursor, count);
+
+ rseek(cursor + count);
+
+ return count;
+}
+
+ssize_t Balau::Buffer::write(const void * buf, size_t count) throw (GeneralException) {
+ off_t cursor = wtell();
+ off_t end = cursor + count;
+ off_t endBlock = (end / s_blockSize) + ((end % s_blockSize) ? 1 : 0);
+ off_t oldEndBlock = m_numBlocks;
+
+ if (endBlock > oldEndBlock) {
+ m_buffer = (uint8_t *) realloc(m_buffer, endBlock * s_blockSize);
+ memset(m_buffer + oldEndBlock * s_blockSize, 0, (endBlock - oldEndBlock) * s_blockSize);
+ }
+
+ memcpy(m_buffer + cursor, buf, count);
+
+ wseek(cursor + count);
+
+ return count;
+}
+
+void Balau::Buffer::reset() {
+ m_buffer = (uint8_t *) realloc(m_buffer, 0);
+ m_bufSize = 0;
+ m_numBlocks = 0;
+ wseek(0);
+ rseek(0);
+}
+
+bool Balau::Buffer::isClosed() {
+ return false;
+}
+
+const char * Balau::Buffer::getName() {
+ return "Buffer";
+}
+
+off_t Balau::Buffer::getSize() {
+ return m_bufSize;
+}
+
+bool Balau::Buffer::canRead() {
+ return true;
+}
+
+bool Balau::Buffer::canWrite() {
+ return true;
+}
diff --git a/tests/test-Handles.cc b/tests/test-Handles.cc
index f9fd055..fd05c76 100644
--- a/tests/test-Handles.cc
+++ b/tests/test-Handles.cc
@@ -1,6 +1,7 @@
#include <Main.h>
#include <Input.h>
#include <Output.h>
+#include <Buffer.h>
#ifdef _WIN32
void ctime_r(const time_t * t, char * str) {
@@ -70,5 +71,16 @@ void MainTask::Do() {
Assert(s == 0);
o->write("foo\n", 4);
+ IO<Handle> b(new Buffer());
+ s = b->rtell();
+ Assert(s == 0);
+ s = b->wtell();
+ Assert(s == 0);
+ b->write("foo\n", 4);
+ s = b->rtell();
+ Assert(s == 0);
+ s = b->wtell();
+ Assert(s == 4);
+
Printer::log(M_STATUS, "Test::Handles passed.");
}