1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-22 17:48:01 +02:00
Beef/BeefLibs/corlib/src/IO/BufferedStream.bf

184 lines
3.9 KiB
Beef
Raw Normal View History

2021-04-11 07:04:17 -04:00
namespace System.IO
{
abstract class BufferedStream : Stream
{
protected int64 mPos;
protected int64 mUnderlyingLength;
protected uint8[] mBuffer ~ delete _;
protected int64 mBufferPos = -Int32.MinValue;
protected int64 mBufferEnd = -Int32.MinValue;
protected int64 mWriteDirtyPos = -Int32.MinValue;
protected int64 mWriteDirtyEnd = -Int32.MinValue;
public override int64 Position
{
get
{
return mPos;
}
set
{
mPos = Math.Min(value, Length);
}
}
public override int64 Length
{
get
{
UpdateLength();
return Math.Max(mUnderlyingLength, mWriteDirtyEnd);
}
}
protected abstract void UpdateLength();
protected abstract Result<int> TryReadUnderlying(int64 pos, Span<uint8> data);
protected abstract Result<int> TryWriteUnderlying(int64 pos, Span<uint8> data);
public ~this()
{
Flush();
}
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
{
int64 length = Length;
int64 newPos;
switch (seekKind)
{
case .Absolute:
mPos = Math.Min(pos, length);
if (pos > length)
return .Err;
case .FromEnd:
newPos = length - pos;
case .Relative:
mPos = Math.Min(mPos + pos, length);
}
return .Ok;
}
public void MakeBuffer(int size)
{
delete mBuffer;
mBuffer = new uint8[size];
}
public override Result<int> TryRead(Span<uint8> data)
{
2021-04-11 07:55:53 -04:00
int spaceLeft = (.)(mBufferEnd - mPos);
2021-04-11 07:04:17 -04:00
if (data.Length <= spaceLeft)
{
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), data.Length);
mPos += data.Length;
return data.Length;
}
int64 readStart = mPos;
var data;
if (spaceLeft > 0)
{
Internal.MemCpy(data.Ptr, mBuffer.Ptr + (mPos - mBufferPos), spaceLeft);
mPos += spaceLeft;
data.RemoveFromStart(spaceLeft);
}
if (mWriteDirtyPos >= 0)
Try!(Flush());
if ((mBuffer == null) || (data.Length > mBuffer.Count))
{
var result = TryReadUnderlying(mPos, data);
if (result case .Ok(let len))
mPos += len;
2021-04-11 07:55:53 -04:00
return (.)(mPos - readStart);
2021-04-11 07:04:17 -04:00
}
var result = TryReadUnderlying(mPos, mBuffer);
switch (result)
{
case .Ok(let len):
mBufferPos = mPos;
mBufferEnd = mPos + len;
int readLen = Math.Min(len, data.Length);
Internal.MemCpy(data.Ptr, mBuffer.Ptr, readLen);
mPos += readLen;
2021-04-11 07:55:53 -04:00
return (.)(mPos - readStart);
2021-04-11 07:04:17 -04:00
case .Err:
return result;
}
}
public override Result<int> TryWrite(Span<uint8> data)
{
var data;
if ((mWriteDirtyEnd >= 0) && (mWriteDirtyEnd != mPos))
{
Try!(Flush());
}
int writeCount = 0;
if (mWriteDirtyEnd >= 0)
{
2021-04-11 07:55:53 -04:00
int spaceLeft = (.)((mBufferPos + mBuffer.Count) - mPos);
2021-04-11 07:04:17 -04:00
if (data.Length <= spaceLeft)
writeCount = data.Length;
else
writeCount = spaceLeft;
if (writeCount > 0)
{
Internal.MemCpy(mBuffer.Ptr + (mPos - mBufferPos), data.Ptr, writeCount);
mPos += writeCount;
mWriteDirtyEnd = Math.Max(mWriteDirtyEnd, mPos);
mBufferEnd = Math.Max(mBufferEnd, mPos);
if (writeCount == data.Length)
return writeCount;
data.RemoveFromStart(writeCount);
}
}
Try!(Flush());
if ((mBuffer == null) || (data.Length > mBuffer.Count))
{
var result = TryWriteUnderlying(mPos, data);
if (result case .Ok(let len))
mPos += len;
writeCount += result;
return writeCount;
}
mBufferPos = mPos;
mWriteDirtyPos = mPos;
Internal.MemCpy(mBuffer.Ptr, data.Ptr, data.Length);
mPos += data.Length;
mBufferEnd = mPos;
mWriteDirtyEnd = mPos;
writeCount += data.Length;
return writeCount;
}
public override Result<void> Flush()
{
if (mWriteDirtyPos >= 0)
{
Try!(TryWriteUnderlying(mWriteDirtyPos, .(mBuffer.Ptr + (mWriteDirtyPos - mBufferPos), (.)(mWriteDirtyEnd - mWriteDirtyPos))));
mWriteDirtyPos = -Int32.MinValue;
mWriteDirtyEnd = -Int32.MinValue;
}
return .Ok;
}
public override Result<void> Close()
{
return Flush();
}
}
}