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
|
ArchivingManagers.cpp
|
||||||
Beep.cpp
|
Beep.cpp
|
||||||
BlockCache.cpp
|
BlockCache.cpp
|
||||||
|
BufferedDataIO.cpp
|
||||||
|
BufferIO.cpp
|
||||||
ByteOrder.cpp
|
ByteOrder.cpp
|
||||||
DataIO.cpp
|
DataIO.cpp
|
||||||
DateTime.cpp
|
DateTime.cpp
|
||||||
BufferIO.cpp
|
|
||||||
Flattenable.cpp
|
Flattenable.cpp
|
||||||
List.cpp
|
List.cpp
|
||||||
Locker.cpp
|
Locker.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user