Merge branch 'release'

# Conflicts:
#	src/SharpCompress/Archives/ArchiveFactory.cs
#	src/SharpCompress/Archives/AutoArchiveFactory.cs
#	src/SharpCompress/Archives/SevenZip/SevenZipArchive.cs
#	src/SharpCompress/Archives/Zip/ZipArchive.cs
#	src/SharpCompress/Factories/AceFactory.cs
#	src/SharpCompress/Factories/ArcFactory.cs
#	src/SharpCompress/Factories/ArjFactory.cs
#	src/SharpCompress/Factories/Factory.cs
#	src/SharpCompress/Factories/GZipFactory.cs
#	src/SharpCompress/Factories/IFactory.cs
#	src/SharpCompress/Factories/RarFactory.cs
#	src/SharpCompress/Factories/SevenZipFactory.cs
#	src/SharpCompress/Factories/TarFactory.cs
#	src/SharpCompress/Factories/ZStandardFactory.cs
#	src/SharpCompress/Factories/ZipFactory.cs
#	src/SharpCompress/IO/SharpCompressStream.cs
#	src/SharpCompress/Readers/AbstractReader.cs
#	src/SharpCompress/Utility.cs
This commit is contained in:
Adam Hathcock
2026-01-28 11:12:49 +00:00
21 changed files with 780 additions and 350 deletions

View File

@@ -24,13 +24,12 @@ public partial class SharpCompressStream
{
ValidateBufferState();
// Fill buffer if needed
// Fill buffer if needed, handling short reads from underlying stream
if (_bufferedLength == 0)
{
_bufferedLength = await Stream
.ReadAsync(_buffer!, 0, _bufferSize, cancellationToken)
.ConfigureAwait(false);
_bufferPosition = 0;
_bufferedLength = await FillBufferAsync(_buffer!, 0, _bufferSize, cancellationToken)
.ConfigureAwait(false);
}
int available = _bufferedLength - _bufferPosition;
int toRead = Math.Min(count, available);
@@ -42,16 +41,9 @@ public partial class SharpCompressStream
return toRead;
}
// If buffer exhausted, refill
int r = await Stream
.ReadAsync(_buffer!, 0, _bufferSize, cancellationToken)
.ConfigureAwait(false);
if (r == 0)
{
return 0;
}
_bufferedLength = r;
_bufferPosition = 0;
_bufferedLength = await FillBufferAsync(_buffer!, 0, _bufferSize, cancellationToken)
.ConfigureAwait(false);
if (_bufferedLength == 0)
{
return 0;
@@ -65,13 +57,47 @@ public partial class SharpCompressStream
else
{
int read = await Stream
.ReadAsync(buffer, offset, count, cancellationToken)
.ConfigureAwait(false);
.ReadAsync(buffer, offset, count, cancellationToken)
.ConfigureAwait(false);
_internalPosition += read;
return read;
}
}
/// <summary>
/// Async version of FillBuffer. Implements the ReadFullyAsync pattern.
/// Reads in a loop until buffer is full or EOF is reached.
/// </summary>
private async Task<int> FillBufferAsync(
byte[] buffer,
int offset,
int count,
CancellationToken cancellationToken
)
{
// Implement ReadFullyAsync pattern but return the actual count read
// This is the same logic as Utility.ReadFullyAsync but returns count instead of bool
var total = 0;
int read;
while (
(
read = await Stream
.ReadAsync(buffer, offset + total, count - total, cancellationToken)
.ConfigureAwait(false)
) > 0
)
{
total += read;
if (total >= count)
{
return total;
}
}
return total;
}
public override async Task WriteAsync(
byte[] buffer,
int offset,
@@ -104,13 +130,15 @@ public partial class SharpCompressStream
{
ValidateBufferState();
// Fill buffer if needed
// Fill buffer if needed, handling short reads from underlying stream
if (_bufferedLength == 0)
{
_bufferedLength = await Stream
.ReadAsync(_buffer.AsMemory(0, _bufferSize), cancellationToken)
.ConfigureAwait(false);
_bufferPosition = 0;
_bufferedLength = await FillBufferMemoryAsync(
_buffer.AsMemory(0, _bufferSize),
cancellationToken
)
.ConfigureAwait(false);
}
int available = _bufferedLength - _bufferPosition;
int toRead = Math.Min(buffer.Length, available);
@@ -122,16 +150,12 @@ public partial class SharpCompressStream
return toRead;
}
// If buffer exhausted, refill
int r = await Stream
.ReadAsync(_buffer.AsMemory(0, _bufferSize), cancellationToken)
.ConfigureAwait(false);
if (r == 0)
{
return 0;
}
_bufferedLength = r;
_bufferPosition = 0;
_bufferedLength = await FillBufferMemoryAsync(
_buffer.AsMemory(0, _bufferSize),
cancellationToken
)
.ConfigureAwait(false);
if (_bufferedLength == 0)
{
return 0;
@@ -150,6 +174,36 @@ public partial class SharpCompressStream
}
}
/// <summary>
/// Async version of FillBuffer for Memory{byte}. Implements the ReadFullyAsync pattern.
/// Reads in a loop until buffer is full or EOF is reached.
/// </summary>
private async ValueTask<int> FillBufferMemoryAsync(
Memory<byte> buffer,
CancellationToken cancellationToken
)
{
// Implement ReadFullyAsync pattern but return the actual count read
var total = 0;
int read;
while (
(
read = await Stream
.ReadAsync(buffer.Slice(total), cancellationToken)
.ConfigureAwait(false)
) > 0
)
{
total += read;
if (total >= buffer.Length)
{
return total;
}
}
return total;
}
public override async ValueTask WriteAsync(
ReadOnlyMemory<byte> buffer,
CancellationToken cancellationToken = default