Added a buffered DataIO subclass.
* Only the read path is tested so far.
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2011, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _BUFFERED_DATA_IO_H
|
||||
#define _BUFFERED_DATA_IO_H
|
||||
|
||||
|
||||
#include <DataIO.h>
|
||||
|
||||
|
||||
class BBufferedDataIO : public BDataIO {
|
||||
public:
|
||||
BBufferedDataIO(BDataIO& stream,
|
||||
size_t bufferSize = 65536L,
|
||||
bool ownsStream = true,
|
||||
bool partialReads = false);
|
||||
virtual ~BBufferedDataIO();
|
||||
|
||||
status_t InitCheck() const;
|
||||
|
||||
BDataIO* Stream() const;
|
||||
size_t BufferSize() const;
|
||||
bool OwnsStream() const;
|
||||
void SetOwnsStream(bool ownsStream);
|
||||
status_t Flush();
|
||||
|
||||
// BDataIO interface
|
||||
virtual ssize_t Read(void* buffer, size_t size);
|
||||
virtual ssize_t Write(const void* buffer, size_t size);
|
||||
|
||||
private:
|
||||
virtual status_t _Reserved0(void*);
|
||||
virtual status_t _Reserved1(void*);
|
||||
virtual status_t _Reserved2(void*);
|
||||
virtual status_t _Reserved3(void*);
|
||||
virtual status_t _Reserved4(void*);
|
||||
|
||||
private:
|
||||
BDataIO& fStream;
|
||||
uint8* fBuffer;
|
||||
size_t fBufferSize;
|
||||
size_t fPosition;
|
||||
size_t fSize;
|
||||
|
||||
uint32 _reserved_ints[4];
|
||||
|
||||
bool fDirty;
|
||||
bool fOwnsStream;
|
||||
bool fPartialReads;
|
||||
|
||||
bool _reserved_bools[5];
|
||||
};
|
||||
|
||||
|
||||
#endif // _BUFFERED_DATA_IO_H
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright 2011, Axel Dörfler, [email protected].
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <BufferedDataIO.h>
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//#define TRACE_DATA_IO
|
||||
#ifdef TRACE_DATA_IO
|
||||
# define TRACE(x...) printf(x)
|
||||
#else
|
||||
# define TRACE(x...) ;
|
||||
#endif
|
||||
|
||||
|
||||
BBufferedDataIO::BBufferedDataIO(BDataIO& stream, size_t bufferSize,
|
||||
bool ownsStream, bool partialReads)
|
||||
:
|
||||
fStream(stream),
|
||||
fPosition(0),
|
||||
fSize(0),
|
||||
fDirty(false),
|
||||
fOwnsStream(ownsStream),
|
||||
fPartialReads(partialReads)
|
||||
{
|
||||
fBufferSize = max_c(bufferSize, 512);
|
||||
fBuffer = new(std::nothrow) uint8[fBufferSize];
|
||||
}
|
||||
|
||||
|
||||
BBufferedDataIO::~BBufferedDataIO()
|
||||
{
|
||||
Flush();
|
||||
delete[] fBuffer;
|
||||
|
||||
if (fOwnsStream)
|
||||
delete &fStream;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BBufferedDataIO::InitCheck() const
|
||||
{
|
||||
return fBuffer == NULL ? B_NO_MEMORY : B_OK;
|
||||
}
|
||||
|
||||
|
||||
BDataIO*
|
||||
BBufferedDataIO::Stream() const
|
||||
{
|
||||
return &fStream;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BBufferedDataIO::BufferSize() const
|
||||
{
|
||||
return fBufferSize;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BBufferedDataIO::OwnsStream() const
|
||||
{
|
||||
return fOwnsStream;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BBufferedDataIO::SetOwnsStream(bool ownsStream)
|
||||
{
|
||||
fOwnsStream = ownsStream;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BBufferedDataIO::Flush()
|
||||
{
|
||||
if (!fDirty)
|
||||
return B_OK;
|
||||
|
||||
size_t bytesWritten = fStream.Write(fBuffer + fPosition, fSize);
|
||||
if (bytesWritten == fSize) {
|
||||
fDirty = false;
|
||||
fPosition = 0;
|
||||
fSize = 0;
|
||||
return B_OK;
|
||||
} else if (bytesWritten >= 0) {
|
||||
fSize -= bytesWritten;
|
||||
fPosition += bytesWritten;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BBufferedDataIO::Read(void* buffer, size_t size)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
TRACE("%p::Read(size %lu)\n", this, size);
|
||||
|
||||
size_t bytesRead = 0;
|
||||
|
||||
if (fSize > 0) {
|
||||
// fill the part of the stream we already have
|
||||
bytesRead = min_c(size, fSize);
|
||||
TRACE("%p: read %lu bytes we already have in the buffer.\n", this,
|
||||
bytesRead);
|
||||
memcpy(buffer, fBuffer + fPosition, bytesRead);
|
||||
|
||||
buffer = (void*)((uint8_t*)buffer + bytesRead);
|
||||
size -= bytesRead;
|
||||
fPosition += bytesRead;
|
||||
fSize -= bytesRead;
|
||||
|
||||
if (fPartialReads)
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
if (size > fBufferSize || fBuffer == NULL) {
|
||||
// request is larger than our buffer, just fill it directly
|
||||
return fStream.Read(buffer, size);
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
// retrieve next buffer
|
||||
|
||||
status_t status = Flush();
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
TRACE("%p: read %" B_PRIuSIZE " bytes from stream\n", this, fBufferSize);
|
||||
fSize = fStream.Read(fBuffer, fBufferSize);
|
||||
TRACE("%p: retrieved %" B_PRIuSIZE " bytes from stream\n", this, fSize);
|
||||
fPosition = 0;
|
||||
|
||||
// Copy the remaining part
|
||||
size_t copy = min_c(size, fSize);
|
||||
memcpy(buffer, fBuffer, copy);
|
||||
TRACE("%p: copy %" B_PRIuSIZE" bytes to buffer\n", this, copy);
|
||||
|
||||
bytesRead += copy;
|
||||
fPosition = copy;
|
||||
fSize -= copy;
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BBufferedDataIO::Write(const void* buffer, size_t size)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
TRACE("%p::Write(size %lu)\n", this, size);
|
||||
|
||||
if (!fDirty) {
|
||||
// Throw away a read-only buffer if necessary
|
||||
TRACE("%p: throw away previous buffer.\n", this);
|
||||
fPosition = 0;
|
||||
fSize = 0;
|
||||
}
|
||||
|
||||
size_t bytesWritten = 0;
|
||||
|
||||
if (size > fBufferSize || fBuffer == NULL) {
|
||||
// request is larger than our buffer, just fill it directly
|
||||
bytesWritten = fSize;
|
||||
|
||||
status_t status = Flush();
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
ssize_t streamWritten = fStream.Write(buffer, size);
|
||||
if (streamWritten >= 0)
|
||||
return bytesWritten + streamWritten;
|
||||
|
||||
return streamWritten;
|
||||
}
|
||||
|
||||
bytesWritten = min_c(size, fBufferSize - fSize - fPosition);
|
||||
TRACE("%p: write %" B_PRIuSIZE " bytes to the buffer.\n", this,
|
||||
bytesWritten);
|
||||
memcpy(fBuffer + fPosition + fSize, buffer, bytesWritten);
|
||||
fSize += bytesWritten;
|
||||
size -= bytesWritten;
|
||||
|
||||
if (size > 0) {
|
||||
status_t status = Flush();
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
memcpy(fBuffer, (uint8*)buffer + bytesWritten, size);
|
||||
fPosition = 0;
|
||||
fSize = size;
|
||||
fDirty = true;
|
||||
bytesWritten += size;
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - FBC
|
||||
|
||||
|
||||
status_t BBufferedDataIO::_Reserved0(void*) { return B_ERROR; }
|
||||
status_t BBufferedDataIO::_Reserved1(void*) { return B_ERROR; }
|
||||
status_t BBufferedDataIO::_Reserved2(void*) { return B_ERROR; }
|
||||
status_t BBufferedDataIO::_Reserved3(void*) { return B_ERROR; }
|
||||
status_t BBufferedDataIO::_Reserved4(void*) { return B_ERROR; }
|
||||
@@ -9,10 +9,11 @@ MergeObject <libbe>support_kit.o :
|
||||
ArchivingManagers.cpp
|
||||
Beep.cpp
|
||||
BlockCache.cpp
|
||||
BufferedDataIO.cpp
|
||||
BufferIO.cpp
|
||||
ByteOrder.cpp
|
||||
DataIO.cpp
|
||||
DateTime.cpp
|
||||
BufferIO.cpp
|
||||
Flattenable.cpp
|
||||
List.cpp
|
||||
Locker.cpp
|
||||
|
||||
Reference in New Issue
Block a user