Skip to content

Commit

Permalink
Implemented GetPositionInBaseStream
Browse files Browse the repository at this point in the history
  • Loading branch information
LTRData committed Nov 20, 2024
1 parent 4e75448 commit 9c103e5
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 14 deletions.
6 changes: 3 additions & 3 deletions Library/DiscUtils.Ntfs/Internals/WofStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public override int Read(Span<byte> buffer)
{
if ((Position & (maxChunkSize - 1)) != 0)
{
throw new ArgumentOutOfRangeException("Read not aligned to compression chunks");
throw new InvalidOperationException("Read not aligned to compression chunks");
}

var total = 0;
Expand Down Expand Up @@ -175,7 +175,7 @@ public override async ValueTask<int> ReadAsync(Memory<byte> buffer, Cancellation
{
if ((Position & (maxChunkSize - 1)) != 0)
{
throw new ArgumentOutOfRangeException("Read not aligned to compression chunks");
throw new InvalidOperationException("Read not aligned to compression chunks");
}

var total = 0;
Expand Down Expand Up @@ -204,7 +204,7 @@ public override int Read(byte[] buffer, int offset, int count)
{
if ((Position & (maxChunkSize - 1)) != 0)
{
throw new ArgumentOutOfRangeException("Read not aligned to compression chunks");
throw new InvalidOperationException("Read not aligned to compression chunks");
}

var total = 0;
Expand Down
4 changes: 4 additions & 0 deletions Library/DiscUtils.Streams/Block/BlockCacheStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -822,10 +822,14 @@ protected override void Dispose(bool disposing)

private void CheckDisposed()
{
#if NET7_0_OR_GREATER
ObjectDisposedException.ThrowIf(_wrappedStream is null, this);
#else
if (_wrappedStream == null)
{
throw new ObjectDisposedException("BlockCacheStream");
}
#endif
}

private void InvalidateBlocks(long firstBlock, int numBlocks)
Expand Down
25 changes: 21 additions & 4 deletions Library/DiscUtils.Streams/ConcatStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,25 +82,38 @@ public override bool CanWrite
}
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this))
{
return virtualPosition;
}

var activeStreamIndex = GetStream(virtualPosition, out var activeStreamStartPos);

var activeStream = _streams[activeStreamIndex];

var basePosition = virtualPosition - activeStreamStartPos;

return activeStream.GetPositionInBaseStream(baseStream, basePosition);
}

public override IEnumerable<StreamExtent> Extents
{
get
{
CheckDisposed();
var extents = new List<StreamExtent>();

long pos = 0;
for (var i = 0; i < _streams.Count; ++i)
{
foreach (var extent in _streams[i].Extents)
{
extents.Add(new StreamExtent(extent.Start + pos, extent.Length));
yield return new StreamExtent(extent.Start + pos, extent.Length);
}

pos += _streams[i].Length;
}

return extents;
}
}

Expand Down Expand Up @@ -388,9 +401,13 @@ private int GetStream(long targetPos, out long streamStartPos)

private void CheckDisposed()
{
#if NET7_0_OR_GREATER
ObjectDisposedException.ThrowIf(_streams is null, this);
#else
if (_streams == null)
{
throw new ObjectDisposedException("ConcatStream");
}
#endif
}
}
11 changes: 11 additions & 0 deletions Library/DiscUtils.Streams/MirrorStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// DEALINGS IN THE SOFTWARE.
//

using DiscUtils.Streams.Compatibility;
using System;
using System.Collections.Generic;
using System.IO;
Expand Down Expand Up @@ -63,6 +64,16 @@ public MirrorStream(Ownership ownsWrapped, IEnumerable<SparseStream> wrapped)
}
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this))
{
return virtualPosition;
}

return _wrapped[0].GetPositionInBaseStream(baseStream, virtualPosition);
}

public override bool CanRead => _canRead;

public override bool CanSeek => _canSeek;
Expand Down
11 changes: 11 additions & 0 deletions Library/DiscUtils.Streams/SnapshotStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ public SnapshotStream(Stream baseStream, Ownership owns)
_diffExtents = [];
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this)
|| _baseStream is not CompatibilityStream baseCompatStream)
{
return virtualPosition;
}

return baseCompatStream.GetPositionInBaseStream(baseStream, virtualPosition);
}

/// <summary>
/// Gets an indication as to whether the stream can be read.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions Library/DiscUtils.Streams/SparseStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,16 @@ public SparseReadOnlyWrapperStream(SparseStream wrapped, Ownership ownsWrapped)
_ownsWrapped = ownsWrapped;
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this))
{
return virtualPosition;
}

return _wrapped.GetPositionInBaseStream(baseStream, virtualPosition);
}

public override bool CanRead
{
get
Expand Down Expand Up @@ -331,6 +341,16 @@ public SparseWrapperStream(Stream wrapped, Ownership ownsWrapped, IEnumerable<St
}
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this))
{
return virtualPosition;
}

return _wrapped.GetPositionInBaseStream(baseStream, virtualPosition);
}

public override bool CanRead
{
get
Expand Down
30 changes: 25 additions & 5 deletions Library/DiscUtils.Streams/StripedStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,26 @@ public StripedStream(long stripeSize, Ownership ownsWrapped, IEnumerable<SparseS
_length = subStreamLength * _wrapped.Count;
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this))
{
return virtualPosition;
}

var stripe = virtualPosition / _stripeSize;
var stripeOffset = virtualPosition % _stripeSize;

var streamIdx = (int)(stripe % _wrapped.Count);
var streamStripe = stripe / _wrapped.Count;

var targetStream = _wrapped[streamIdx];

var targetStreamPosition = streamStripe * _stripeSize + stripeOffset;

return targetStream.GetPositionInBaseStream(baseStream, targetStreamPosition);
}

public override bool CanRead => _canRead;

public override bool CanSeek => true;
Expand Down Expand Up @@ -116,7 +136,7 @@ public override int Read(byte[] buffer, int offset, int count)
var streamIdx = (int)(stripe % _wrapped.Count);
var streamStripe = stripe / _wrapped.Count;

Stream targetStream = _wrapped[streamIdx];
var targetStream = _wrapped[streamIdx];
targetStream.Position = streamStripe * _stripeSize + stripeOffset;

var numRead = targetStream.Read(buffer, offset + totalRead, stripeToRead);
Expand Down Expand Up @@ -146,7 +166,7 @@ public override async ValueTask<int> ReadAsync(Memory<byte> buffer, Cancellation
var streamIdx = (int)(stripe % _wrapped.Count);
var streamStripe = stripe / _wrapped.Count;

Stream targetStream = _wrapped[streamIdx];
var targetStream = _wrapped[streamIdx];
targetStream.Position = streamStripe * _stripeSize + stripeOffset;

var numRead = await targetStream.ReadAsync(buffer.Slice(totalRead, stripeToRead), cancellationToken).ConfigureAwait(false);
Expand Down Expand Up @@ -238,7 +258,7 @@ public override void Write(byte[] buffer, int offset, int count)
var streamIdx = (int)(stripe % _wrapped.Count);
var streamStripe = stripe / _wrapped.Count;

Stream targetStream = _wrapped[streamIdx];
var targetStream = _wrapped[streamIdx];
targetStream.Position = streamStripe * _stripeSize + stripeOffset;
targetStream.Write(buffer, offset + totalWritten, stripeToWrite);

Expand Down Expand Up @@ -269,7 +289,7 @@ public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, Cancella
var streamIdx = (int)(stripe % _wrapped.Count);
var streamStripe = stripe / _wrapped.Count;

Stream targetStream = _wrapped[streamIdx];
var targetStream = _wrapped[streamIdx];
targetStream.Position = streamStripe * _stripeSize + stripeOffset;
await targetStream.WriteAsync(buffer.Slice(totalWritten, stripeToWrite), cancellationToken).ConfigureAwait(false);

Expand Down Expand Up @@ -300,7 +320,7 @@ public override void Write(ReadOnlySpan<byte> buffer)
var streamIdx = (int)(stripe % _wrapped.Count);
var streamStripe = stripe / _wrapped.Count;

Stream targetStream = _wrapped[streamIdx];
var targetStream = _wrapped[streamIdx];
targetStream.Position = streamStripe * _stripeSize + stripeOffset;
targetStream.Write(buffer.Slice(totalWritten, stripeToWrite));

Expand Down
15 changes: 15 additions & 0 deletions Library/DiscUtils.Streams/SubStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,21 @@ public override IEnumerable<StreamExtent> Extents
}
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this))
{
return virtualPosition;
}

if (_parent is CompatibilityStream baseCompatStream)
{
return baseCompatStream.GetPositionInBaseStream(baseStream, _first + virtualPosition);
}

return _first + virtualPosition;
}

public override long Length => _length;

public override long Position
Expand Down
25 changes: 23 additions & 2 deletions Library/DiscUtils.Streams/ThreadSafeStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// DEALINGS IN THE SOFTWARE.
//

using DiscUtils.Streams.Compatibility;
using System;
using System.Collections.Generic;
using System.IO;
Expand Down Expand Up @@ -87,10 +88,26 @@ public ThreadSafeStream(SparseStream toWrap, Ownership ownership)
private ThreadSafeStream(ThreadSafeStream toClone)
{
_common = toClone._common;

#if NET7_0_OR_GREATER
ObjectDisposedException.ThrowIf(_common is null, toClone);
#else
if (_common == null)
{
throw new ObjectDisposedException("toClone");
}
#endif
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this)
|| _common.WrappedStream is not CompatibilityStream baseCompatStream)
{
return virtualPosition;
}

return baseCompatStream.GetPositionInBaseStream(baseStream, virtualPosition);
}

/// <summary>
Expand Down Expand Up @@ -169,8 +186,12 @@ private SparseStream Wrapped
{
get
{
var wrapped = _common.WrappedStream ?? throw new ObjectDisposedException("ThreadSafeStream");
return wrapped;
#if NET7_0_OR_GREATER
ObjectDisposedException.ThrowIf(_common.WrappedStream is null, this);
return _common.WrappedStream;
#else
return _common.WrappedStream ?? throw new ObjectDisposedException("ThreadSafeStream");
#endif
}
}

Expand Down
39 changes: 39 additions & 0 deletions Library/DiscUtils.Streams/Util/CompatExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ namespace DiscUtils.Streams.Compatibility;

public abstract class CompatibilityStream : Stream
{
/// <summary>
/// In a derived class, get corresponding position in a base stream of this instance
/// to a position in this instance.
/// </summary>
public virtual long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (baseStream is null
|| ReferenceEquals(baseStream, this))
{
return virtualPosition;
}

return null;
}

public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
#if NET6_0_OR_GREATER
Expand Down Expand Up @@ -241,5 +256,29 @@ public static void AppendData(this IncrementalHash hash, ReadOnlySpan<byte> data
public static Task CopyToAsync(this Stream source, Stream target, CancellationToken cancellationToken)
=> source.CopyToAsync(target, bufferSize: 80 * 1024, cancellationToken);
#endif

/// <summary>
/// If stream is derived from CompatibilityStream, get corresponding position in a base stream of this instance
/// to a position in this instance.
/// </summary>
public static long? GetPositionInBaseStream(this Stream stream, Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(stream, baseStream))
{
return virtualPosition;
}

if (stream is CompatibilityStream compatBaseStream)
{
return compatBaseStream.GetPositionInBaseStream(baseStream, virtualPosition);
}

if (baseStream is null)
{
return virtualPosition;
}

return null;
}
}

11 changes: 11 additions & 0 deletions Library/DiscUtils.Streams/WrappingMappedStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ public WrappingMappedStream(T toWrap, Ownership ownership, IEnumerable<StreamExt
}
}

public override long? GetPositionInBaseStream(Stream baseStream, long virtualPosition)
{
if (ReferenceEquals(baseStream, this)
|| WrappedStream is not CompatibilityStream baseCompatStream)
{
return virtualPosition;
}

return baseCompatStream.GetPositionInBaseStream(baseStream, virtualPosition);
}

public override bool CanRead => WrappedStream.CanRead;

public override bool CanSeek => WrappedStream.CanSeek;
Expand Down
Loading

0 comments on commit 9c103e5

Please sign in to comment.