mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 07:25:11 +00:00
Consolidate ReadExact and ReadFully methods into Utility.cs
Co-authored-by: adamhathcock <527620+adamhathcock@users.noreply.github.com>
This commit is contained in:
@@ -29,57 +29,35 @@ namespace SharpCompress.Common
|
||||
|
||||
public async ValueTask<byte> ReadByteAsync(CancellationToken ct = default)
|
||||
{
|
||||
await ReadExactAsync(_buffer, 0, 1, ct).ConfigureAwait(false);
|
||||
await _stream.ReadExactAsync(_buffer, 0, 1, ct).ConfigureAwait(false);
|
||||
return _buffer[0];
|
||||
}
|
||||
|
||||
public async ValueTask<ushort> ReadUInt16Async(CancellationToken ct = default)
|
||||
{
|
||||
await ReadExactAsync(_buffer, 0, 2, ct).ConfigureAwait(false);
|
||||
await _stream.ReadExactAsync(_buffer, 0, 2, ct).ConfigureAwait(false);
|
||||
return BinaryPrimitives.ReadUInt16LittleEndian(_buffer);
|
||||
}
|
||||
|
||||
public async ValueTask<uint> ReadUInt32Async(CancellationToken ct = default)
|
||||
{
|
||||
await ReadExactAsync(_buffer, 0, 4, ct).ConfigureAwait(false);
|
||||
await _stream.ReadExactAsync(_buffer, 0, 4, ct).ConfigureAwait(false);
|
||||
return BinaryPrimitives.ReadUInt32LittleEndian(_buffer);
|
||||
}
|
||||
|
||||
public async ValueTask<ulong> ReadUInt64Async(CancellationToken ct = default)
|
||||
{
|
||||
await ReadExactAsync(_buffer, 0, 8, ct).ConfigureAwait(false);
|
||||
await _stream.ReadExactAsync(_buffer, 0, 8, ct).ConfigureAwait(false);
|
||||
return BinaryPrimitives.ReadUInt64LittleEndian(_buffer);
|
||||
}
|
||||
|
||||
public async ValueTask<byte[]> ReadBytesAsync(int count, CancellationToken ct = default)
|
||||
{
|
||||
var result = new byte[count];
|
||||
await ReadExactAsync(result, 0, count, ct).ConfigureAwait(false);
|
||||
await _stream.ReadExactAsync(result, 0, count, ct).ConfigureAwait(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
private async ValueTask ReadExactAsync(
|
||||
byte[] destination,
|
||||
int offset,
|
||||
int length,
|
||||
CancellationToken ct
|
||||
)
|
||||
{
|
||||
var read = 0;
|
||||
while (read < length)
|
||||
{
|
||||
var n = await _stream
|
||||
.ReadAsync(destination, offset + read, length - read, ct)
|
||||
.ConfigureAwait(false);
|
||||
if (n == 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
read += n;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
|
||||
@@ -53,39 +53,4 @@ internal static class Utils
|
||||
throw new InvalidOperationException("Assertion failed.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadExact(this Stream stream, byte[] buffer, int offset, int length)
|
||||
{
|
||||
if (stream is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
|
||||
if (buffer is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
|
||||
if (length < 0 || length > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(length));
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var fetched = stream.Read(buffer, offset, length);
|
||||
if (fetched <= 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
offset += fetched;
|
||||
length -= fetched;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,23 +11,11 @@ public static class BinaryReaderExtensions
|
||||
{
|
||||
public async Task<byte> ReadByteAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(1);
|
||||
try
|
||||
{
|
||||
var bytesRead = await reader
|
||||
.BaseStream.ReadAsync(buffer, 0, 1, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (bytesRead != 1)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
return buffer[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
var buffer = new byte[1];
|
||||
await reader
|
||||
.BaseStream.ReadExactAsync(buffer, 0, 1, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
return buffer[0];
|
||||
}
|
||||
|
||||
public async Task<byte[]> ReadBytesAsync(
|
||||
@@ -35,24 +23,11 @@ public static class BinaryReaderExtensions
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
var buffer = ArrayPool<byte>.Shared.Rent(count);
|
||||
try
|
||||
{
|
||||
var bytesRead = await reader
|
||||
.BaseStream.ReadAsync(buffer, 0, 1, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (bytesRead != count)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
var bytes = new byte[count];
|
||||
System.Buffer.BlockCopy(buffer, 0, bytes, 0, count);
|
||||
return bytes;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(buffer);
|
||||
}
|
||||
var bytes = new byte[count];
|
||||
await reader
|
||||
.BaseStream.ReadExactAsync(bytes, 0, count, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,20 +98,9 @@ public static class StreamExtensions
|
||||
int offset,
|
||||
int count,
|
||||
CancellationToken cancellationToken
|
||||
)
|
||||
{
|
||||
var totalRead = 0;
|
||||
while (totalRead < count)
|
||||
{
|
||||
var read = await stream
|
||||
.ReadAsync(buffer, offset + totalRead, count - totalRead, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (read == 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
totalRead += read;
|
||||
}
|
||||
}
|
||||
) =>
|
||||
await stream
|
||||
.ReadExactAsync(buffer, offset, count, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +273,33 @@ internal static class Utility
|
||||
}
|
||||
}
|
||||
|
||||
#if NET60_OR_GREATER
|
||||
public bool ReadFully(byte[] buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
source.ReadExactly(buffer);
|
||||
return true;
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReadFully(Span<byte> buffer)
|
||||
{
|
||||
try
|
||||
{
|
||||
source.ReadExactly(buffer);
|
||||
return true;
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
public bool ReadFully(byte[] buffer)
|
||||
{
|
||||
var total = 0;
|
||||
@@ -302,6 +329,7 @@ internal static class Utility
|
||||
}
|
||||
return (total >= buffer.Length);
|
||||
}
|
||||
#endif
|
||||
|
||||
public async Task<bool> ReadFullyAsync(
|
||||
byte[] buffer,
|
||||
@@ -354,36 +382,89 @@ internal static class Utility
|
||||
}
|
||||
}
|
||||
|
||||
#if NET60_OR_GREATER
|
||||
|
||||
public static bool ReadFully(this Stream stream, byte[] buffer)
|
||||
/// <summary>
|
||||
/// Read exactly the requested number of bytes from a stream. Throws EndOfStreamException if not enough data is available.
|
||||
/// </summary>
|
||||
public static void ReadExact(this Stream stream, byte[] buffer, int offset, int length)
|
||||
{
|
||||
try
|
||||
if (stream is null)
|
||||
{
|
||||
stream.ReadExactly(buffer);
|
||||
return true;
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
|
||||
if (buffer is null)
|
||||
{
|
||||
return false;
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
|
||||
if (length < 0 || length > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(length));
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var fetched = stream.Read(buffer, offset, length);
|
||||
if (fetched <= 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
offset += fetched;
|
||||
length -= fetched;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool ReadFully(this Stream stream, Span<byte> buffer)
|
||||
/// <summary>
|
||||
/// Read exactly the requested number of bytes from a stream asynchronously. Throws EndOfStreamException if not enough data is available.
|
||||
/// </summary>
|
||||
public static async Task ReadExactAsync(
|
||||
this Stream stream,
|
||||
byte[] buffer,
|
||||
int offset,
|
||||
int length,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
try
|
||||
if (stream is null)
|
||||
{
|
||||
stream.ReadExactly(buffer);
|
||||
return true;
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
|
||||
if (buffer is null)
|
||||
{
|
||||
return false;
|
||||
throw new ArgumentNullException(nameof(buffer));
|
||||
}
|
||||
|
||||
if (offset < 0 || offset > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
|
||||
if (length < 0 || length > buffer.Length - offset)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(length));
|
||||
}
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
var fetched = await stream
|
||||
.ReadAsync(buffer, offset, length, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
if (fetched <= 0)
|
||||
{
|
||||
throw new EndOfStreamException();
|
||||
}
|
||||
|
||||
offset += fetched;
|
||||
length -= fetched;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
public static string TrimNulls(this string source) => source.Replace('\0', ' ').Trim();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user