From e6385cb74c35eb5a346237acecc846e52c4d6bd4 Mon Sep 17 00:00:00 2001 From: Pixel Date: Sat, 12 Nov 2011 21:52:02 +0100 Subject: Adding seekable buffers. Probably would need a few more tests in the Handles unit test. --- Makefile | 1 + includes/Buffer.h | 24 ++++++++++++++++ src/Buffer.cc | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ tests/test-Handles.cc | 12 ++++++++ 4 files changed, 113 insertions(+) create mode 100644 includes/Buffer.h create mode 100644 src/Buffer.cc 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 + +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 +#include +#include +#include +#include +#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 #include #include +#include #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 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."); } -- cgit v1.2.3