diff options
author | Pixel <pixel@nobis-crew.org> | 2011-11-12 21:52:02 +0100 |
---|---|---|
committer | Pixel <pixel@nobis-crew.org> | 2011-11-12 21:52:02 +0100 |
commit | e6385cb74c35eb5a346237acecc846e52c4d6bd4 (patch) | |
tree | c3feffa44aea1a327f67a6298bf76f9d60cd41bc | |
parent | eb773a11ab557e01569b95254d7e21a53706640d (diff) |
Adding seekable buffers. Probably would need a few more tests in the Handles unit test.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | includes/Buffer.h | 24 | ||||
-rw-r--r-- | src/Buffer.cc | 76 | ||||
-rw-r--r-- | tests/test-Handles.cc | 12 |
4 files changed, 113 insertions, 0 deletions
@@ -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."); } |