#include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "Buffer.h" #include "generic.h" Buffer::Buffer(bool _seekable) : Handle(-1), buffer(0), zero(0), realsiz(0), bufsiz(0), ptr(0), seekable(_seekable) { } Buffer::~Buffer() { free(buffer); } Buffer::Buffer(const Buffer & b) : Handle(-1), buffer(0), zero(b.zero), realsiz(b.realsiz), bufsiz(b.bufsiz), ptr(b.ptr), seekable(b.seekable) { buffer = (Byte *) malloc(bufsiz); memcpy(buffer, b.buffer, bufsiz); } ssize_t Buffer::write(const void *buf, size_t count) throw (GeneralException) { if (!count) { return 0; } if (count + realsiz > bufsiz) { int numblocks = (count + realsiz) / realloc_threshold; int remains = (count + realsiz) % realloc_threshold; buffer = (Byte *) realloc(buffer, bufsiz = ((numblocks + (remains ? 1 : 0)) * realloc_threshold)); } memcpy(buffer + realsiz, buf, count); realsiz += count; return count; } ssize_t Buffer::read(void *buf, size_t count) throw (GeneralException) { count = MIN(count, realsiz - ptr); if (!count) { return 0; } memcpy(buf, buffer + ptr, count); ptr += count; if (!seekable) { if (ptr >= realloc_threshold) { int numblocks = (bufsiz / realloc_threshold) - (ptr / realloc_threshold); memmove(buffer, buffer + (bufsiz - numblocks * realloc_threshold), numblocks * realloc_threshold); ptr -= (bufsiz - numblocks * realloc_threshold); realsiz -= (bufsiz - numblocks * realloc_threshold); buffer = (Byte *) realloc(buffer, bufsiz = (numblocks * realloc_threshold)); } } return count; } bool Buffer::CanRead() const { return true; } bool Buffer::CanWrite() const { return true; } String Buffer::GetName() const { return "Buffer"; } Buffer Buffer::operator=(const Buffer & b) { if (b.buffer != buffer) { free(buffer); realsiz = b.realsiz; ptr = b.ptr; seekable = b.seekable; if ((bufsiz = b.bufsiz)) { buffer = (Byte *) malloc(bufsiz); memcpy(buffer, b.buffer, realsiz); } else { buffer = 0; } } return *this; } bool Buffer::CanWatch() const { return false; } ssize_t Buffer::GetSize() const { return realsiz; } Byte Buffer::operator[](size_t p) const { if (p >= realsiz) { return 0; } else { if (seekable) { return buffer[p]; } else { return buffer[ptr + p]; } } } Byte & Buffer::operator[](size_t p) { if (p > bufsiz) { int numblocks = p / realloc_threshold; int remains = p % realloc_threshold; buffer = (Byte *) realloc(buffer, bufsiz = ((numblocks + (remains ? 1 : 0)) * realloc_threshold)); } if (p >= realsiz) { memset(buffer + realsiz, 0, p - realsiz); realsiz = p; } if (seekable) { return buffer[p]; } else { return buffer[ptr + p]; } } bool Buffer::CanSeek() const { return seekable; } off_t Buffer::seek(off_t off, int wheel) throw (GeneralException) { if (!seekable) { throw GeneralException("This buffer is a fifo, thus is not seekable"); } switch (wheel) { case SEEK_SET: ptr = off; break; case SEEK_CUR: ptr += off; break; case SEEK_END: ptr = realsiz + off; break; } operator[](ptr) = operator[](ptr); return ptr; } off_t Buffer::tell() const { return ptr; }