#include "InMemoryBuffer.h" #include "Either.h" #include "Text.h" using namespace Framework; InMemoryBuffer::InMemoryBuffer() : ReferenceCounter() { buffer = new char*[1]; buffer[0] = new char[256]; numBuffers = 1; readPos = 0; writePos = 0; maxWritePos = 0; } InMemoryBuffer::~InMemoryBuffer() { for (int i = 0; i < numBuffers; i++) delete[] buffer[i]; delete[] buffer; } //! Reads from the resource //! \param bytes An array to be filled with bytes from the resource //! \param len How many bytes should be read from the resource void InMemoryBuffer::read(char* bytes, int len) { if (readPos < writePos) { len = MIN(len, writePos - readPos); int readCount = 0; do { int curPos = readPos % 256; int tmp = MIN(len, 256 - curPos); memcpy(bytes + readCount, buffer[readPos / 256] + curPos, tmp); readCount += tmp; readPos += tmp; len -= tmp; } while (len > 0); } } //! Writes to the resource //! \param bytes An array containing the bytes to be written to the resource //! \param len How many bytes should be written to the resource void InMemoryBuffer::write(const char* bytes, int len) { if (numBuffers * 256 < writePos + len) { int newSize = (writePos + len) / 256 + 1; char** newBuffer = new char*[newSize]; memcpy(newBuffer, buffer, sizeof(char*) * numBuffers); memset( newBuffer + numBuffers, 0, sizeof(char*) * (newSize - numBuffers)); delete[] buffer; buffer = newBuffer; numBuffers = newSize; } int writeCount = 0; do { int curPos = writePos % 256; int tmp = MIN(len, 256 - curPos); if (!buffer[writePos / 256]) buffer[writePos / 256] = new char[256]; memcpy(buffer[writePos / 256] + curPos, bytes + writeCount, tmp); writeCount += tmp; writePos += tmp; len -= tmp; } while (len > 0); maxWritePos = MAX(maxWritePos, writePos); } //! Reads the next line of the resource //! \return The read line as Text with line break Text* InMemoryBuffer::readLine() { if (isEnd()) return 0; Text* ret = new Text(""); for (char c = 0; c != '\n' && readPos < writePos;) { read(&c, 1); if (c) ret->append(&c, 1); } return ret; } //! Checks whether the resource has been fully read //! return 1 if the resource has been fully read. 0 otherwise bool InMemoryBuffer::isEnd() const { return readPos < writePos; } //! Sets the position of the byte to be read next //! \param pos The index of the byte //! \param ende 1 if the index counts from the end of the resource. 0 if the index //! counts from the beginning of the resource void InMemoryBuffer::setLPosition(__int64 pos, bool ende) { if (ende) readPos = MAX(0, maxWritePos - (int)pos); else readPos = MIN(maxWritePos, (int)pos); } //! Sets the position of the byte to be written next //! \param pos The index of the byte //! \param ende 1 if the index counts from the end of the resource. 0 if the index //! counts from the beginning of the resource void InMemoryBuffer::setSPosition(__int64 pos, bool ende) { if (ende) writePos = MAX(0, maxWritePos - (int)pos); else writePos = MIN(maxWritePos, (int)pos); } //! Returns the index of the byte from the resource that would be read next //! return -1 if an error occurred. Otherwise the position of the read pointer __int64 InMemoryBuffer::getLPosition() const { return readPos; } //! Returns the index of the byte from the resource that would be written next //! return -1 if an error occurred. Otherwise the position of the write pointer __int64 InMemoryBuffer::getSPosition() const { return writePos; } //! Returns the number of bytes to be read __int64 InMemoryBuffer::getSize() const { return maxWritePos; }