Initial checkin. Partially abstract base class for a DataStream object
that simulates a contiguous stream out of one or more not-necessarily- contiguous extents in another stream. Fully implemented, completely untested. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5697 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
36f786dc8f
commit
0ab79adc28
288
src/apps/bin/makeudfimage/SimulatedStream.cpp
Normal file
288
src/apps/bin/makeudfimage/SimulatedStream.cpp
Normal file
@ -0,0 +1,288 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/*! \file SimulatedStream.cpp
|
||||
*/
|
||||
|
||||
#include "SimulatedStream.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
SimulatedStream::SimulatedStream(DataStream &stream)
|
||||
: fPosition(0)
|
||||
, fStream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
ssize_t
|
||||
SimulatedStream::Read(void *_buffer, size_t size)
|
||||
{
|
||||
uint8 *buffer = reinterpret_cast<uint8*>(_buffer);
|
||||
status_t error = buffer ? B_OK : B_BAD_VALUE;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(fPosition, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.ReadAt(extent.offset, buffer, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
fPosition += bytes;
|
||||
buffer += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
SimulatedStream::ReadAt(off_t pos, void *_buffer, size_t size)
|
||||
{
|
||||
uint8 *buffer = reinterpret_cast<uint8*>(_buffer);
|
||||
status_t error = buffer ? B_OK : B_BAD_VALUE;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(pos, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.ReadAt(extent.offset, buffer, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
pos += bytes;
|
||||
buffer += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
/*! \brief Writes \a size bytes worth of data from \a buffer at the current
|
||||
position in the stream, incrementing the stream's position marker as it goes.
|
||||
*/
|
||||
ssize_t
|
||||
SimulatedStream::Write(const void *_buffer, size_t size)
|
||||
{
|
||||
const uint8 *buffer = reinterpret_cast<const uint8*>(_buffer);
|
||||
status_t error = buffer ? B_OK : B_BAD_VALUE;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(fPosition, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.WriteAt(extent.offset, buffer, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
fPosition += bytes;
|
||||
buffer += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
/*! \brief Writes \a size bytes worth of data from \a buffer at position
|
||||
\a pos in the stream without incrementing the stream's position marker.
|
||||
*/
|
||||
ssize_t
|
||||
SimulatedStream::WriteAt(off_t pos, const void *_buffer, size_t size)
|
||||
{
|
||||
const uint8 *buffer = reinterpret_cast<const uint8*>(_buffer);
|
||||
status_t error = buffer ? B_OK : B_BAD_VALUE;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(pos, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.WriteAt(extent.offset, buffer, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
pos += bytes;
|
||||
buffer += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
/*! \brief Writes \a size bytes worth of data from \a data at the current
|
||||
position in the stream, incrementing the stream's position marker as it goes.
|
||||
*/
|
||||
ssize_t
|
||||
SimulatedStream::Write(BDataIO &data, size_t size)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(fPosition, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.WriteAt(extent.offset, data, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
fPosition += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
/*! \brief Writes \a size bytes worth of data from \a data at position
|
||||
\a pos in the stream without incrementing the stream's position marker.
|
||||
*/
|
||||
ssize_t
|
||||
SimulatedStream::WriteAt(off_t pos, BDataIO &data, size_t size)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(pos, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.WriteAt(extent.offset, data, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
pos += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
/*! \brief Writes \a size bytes worth of zeros at the current position
|
||||
in the stream, incrementing the stream's position marker as it goes.
|
||||
*/
|
||||
ssize_t
|
||||
SimulatedStream::Zero(size_t size)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(fPosition, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.ZeroAt(extent.offset, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
fPosition += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
/*! \brief Writes \a size bytes worth of zeros at position \a pos
|
||||
in the stream without incrementing the stream's position marker.
|
||||
*/
|
||||
ssize_t
|
||||
SimulatedStream::ZeroAt(off_t pos, size_t size)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
ssize_t bytesTotal = 0;
|
||||
while (error == B_OK && size > 0) {
|
||||
data_extent extent;
|
||||
error = _GetExtent(pos, size, extent);
|
||||
if (!error) {
|
||||
if (extent.size > 0) {
|
||||
ssize_t bytes = fStream.ZeroAt(extent.offset, extent.size);
|
||||
if (bytes >= 0) {
|
||||
size -= bytes;
|
||||
pos += bytes;
|
||||
bytesTotal += bytes;
|
||||
} else {
|
||||
error = status_t(bytes);
|
||||
}
|
||||
} else {
|
||||
// end of simulated stream
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return !error ? bytesTotal : ssize_t(error);
|
||||
}
|
||||
|
||||
off_t
|
||||
SimulatedStream::Seek(off_t pos, uint32 seek_mode)
|
||||
{
|
||||
off_t size = _Size();
|
||||
switch (seek_mode) {
|
||||
case SEEK_SET:
|
||||
fPosition = pos;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
fPosition += pos;
|
||||
break;
|
||||
case SEEK_END:
|
||||
fPosition = size + pos;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// Range check
|
||||
if (fPosition < 0)
|
||||
fPosition = 0;
|
||||
else if (fPosition > size && SetSize(fPosition) != B_OK)
|
||||
fPosition = size;
|
||||
return fPosition;
|
||||
}
|
76
src/apps/bin/makeudfimage/SimulatedStream.h
Normal file
76
src/apps/bin/makeudfimage/SimulatedStream.h
Normal file
@ -0,0 +1,76 @@
|
||||
//----------------------------------------------------------------------
|
||||
// This software is part of the OpenBeOS distribution and is covered
|
||||
// by the OpenBeOS license.
|
||||
//
|
||||
// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/*! \file SimulatedStream.h
|
||||
*/
|
||||
|
||||
#ifndef _SIMULATED_STREAM_H
|
||||
#define _SIMULATED_STREAM_H
|
||||
|
||||
#include "DataStream.h"
|
||||
|
||||
/*! \brief Abstract DataStream wrapper around another DataStream and a sequence of
|
||||
extents in said stream that allows for easy write access to said sequence
|
||||
of extents as though they were a continuous chunk of data.
|
||||
|
||||
NOTE: The SimulatedStream object never modifies the data stream position
|
||||
of the underlying data stream; all read/write/zero calls use the underlying
|
||||
stream's ReadAt()/WriteAt()/ZeroAt() functions.
|
||||
*/
|
||||
class SimulatedStream : public DataStream {
|
||||
public:
|
||||
SimulatedStream(DataStream &stream);
|
||||
|
||||
virtual ssize_t Read(void *buffer, size_t size);
|
||||
virtual ssize_t ReadAt(off_t pos, void *buffer, size_t size);
|
||||
|
||||
virtual ssize_t Write(const void *buffer, size_t size);
|
||||
virtual ssize_t WriteAt(off_t pos, const void *buffer, size_t size);
|
||||
|
||||
virtual ssize_t Write(BDataIO &data, size_t size);
|
||||
virtual ssize_t WriteAt(off_t pos, BDataIO &data, size_t size);
|
||||
|
||||
virtual ssize_t Zero(size_t size);
|
||||
virtual ssize_t ZeroAt(off_t pos, size_t size);
|
||||
|
||||
virtual off_t Seek(off_t pos, uint32 seek_mode);
|
||||
virtual off_t Position() const { return fPosition; }
|
||||
|
||||
virtual status_t SetSize(off_t size) { return B_ERROR; }
|
||||
|
||||
protected:
|
||||
struct data_extent {
|
||||
data_extent(off_t offset = 0, size_t size = 0)
|
||||
: offset(offset)
|
||||
, size(size)
|
||||
{
|
||||
}
|
||||
|
||||
off_t offset;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/*! \brief Should be implemented to return (via the output parameter
|
||||
\a extent) the largest extent in the underlying data stream corresponding
|
||||
to the extent in the simulated data stream starting at byte position
|
||||
\a pos of byte length \a size.
|
||||
|
||||
NOTE: If the position is at or beyond the end of the simulated stream, the
|
||||
function should return B_OK, and the value of extent.size should be 0.
|
||||
*/
|
||||
virtual status_t _GetExtent(off_t pos, size_t size, data_extent &extent) = 0;
|
||||
|
||||
/*! \brief Should be implemented to return the current size of the stream.
|
||||
*/
|
||||
virtual off_t _Size() = 0;
|
||||
|
||||
private:
|
||||
off_t fPosition;
|
||||
DataStream &fStream;
|
||||
};
|
||||
|
||||
#endif // _SIMULATED_STREAM_H
|
Loading…
Reference in New Issue
Block a user