You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
8.3 KiB

using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Tools
{
public static class ExStreamTools
{
public static void CopyTo(this Stream input, Stream output, int buffersize, long bytes)
{
byte[] buffer = new byte[buffersize];
int count;
while (bytes > 0L && (count = input.Read(buffer, 0, (int)Math.Min((long)buffer.Length, bytes))) > 0)
{
output.Write(buffer, 0, count);
bytes -= (long)count;
}
}
public static async Task CopyToAsync(this Stream input, Stream output, int buffersize, long bytes, CancellationToken token =default)
{
byte[] buffer = new byte[buffersize];
int count;
while (bytes > 0L && (count = await input.ReadAsync(buffer, 0, (int)Math.Min((long)buffer.Length, bytes), token)) > 0)
{
await output.WriteAsync(buffer, 0, count, token);
bytes -= (long)count;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteValueUnmanaged<T>(this Stream s, T t) where T : unmanaged
{
byte[] buffer = new byte[sizeof(T)];
fixed (byte* ptr = buffer)
{
*(T*)ptr = t;
}
s.Write(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Task WriteValueUnmanagedAsync<T>(this Stream s, T t, CancellationToken token = default) where T : unmanaged
{
byte[] buffer = new byte[sizeof(T)];
fixed (byte* ptr = buffer)
{
*(T*)ptr = t;
}
return s.WriteAsync(buffer, 0, buffer.Length, token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAll(this Stream s, byte[] buffer)
{
s.Write(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task WriteAllAsync(this Stream s, byte[] buffer, CancellationToken token=default)
{
return s.WriteAsync(buffer, 0, buffer.Length,token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ReadAll(this Stream s, byte[] buffer)
{
return s.Read(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task<int> ReadAllAsync(this Stream s, byte[] buffer, CancellationToken token = default)
{
return s.ReadAsync(buffer, 0, buffer.Length, token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ReadAllBlocking(this Stream s, byte[] buffer)
{
return s.BlockingRead(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task<int> ReadAllBlockingAsync(this Stream s, byte[] buffer, CancellationToken token = default)
{
return s.BlockingReadAsync(buffer, 0, buffer.Length, token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] ReadNew(this Stream s, int len)
{
byte[] buffer = new byte[len];
s.Read(buffer, 0, len);
return buffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<byte[]> ReadNewAsync(this Stream s, int len, CancellationToken token = default)
{
byte[] buffer = new byte[len];
await s.ReadAsync(buffer, 0, len, token);
return buffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] ReadNewBlocking(this Stream s, int len)
{
byte[] buffer = new byte[len];
s.BlockingRead(buffer, 0, len);
return buffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<byte[]> ReadNewBlockingAsync(this Stream s, int len, CancellationToken token = default)
{
byte[] buffer = new byte[len];
await s.BlockingReadAsync(buffer, 0, len, token);
return buffer;
}
public static int BlockingRead(this Stream s, byte[] buffer, int offset, int count)
{
int read;
int rlen = 0;
while ((rlen += (read = s.Read(buffer, offset + rlen, count - rlen))) < count) if (read <= 0) break;
return rlen;
}
public static async Task<int> BlockingReadAsync(this Stream s, byte[] buffer, int offset, int count, CancellationToken token=default)
{
int read;
int rlen = 0;
while ((rlen += (read = await s.ReadAsync(buffer, offset + rlen, count - rlen, token))) < count) if (read <= 0) break;
return rlen;
}
public static void WriteString(this Stream s, string str, Encoding encoding = null)
{
if (encoding == null) encoding = Encoding.UTF8;
int code = encoding.CodePage;
byte[] buf = encoding.GetBytes(str);
s.WriteValueUnmanaged(buf.Length);
s.WriteValueUnmanaged(code);
s.WriteAll(buf);
}
public static Task WriteStringAsync(this Stream s, string str, CancellationToken token = default)
=> WriteStringAsync(s, str, Encoding.UTF8, token);
public static async Task WriteStringAsync(this Stream s, string str, Encoding encoding, CancellationToken token=default)
{
int code = encoding.CodePage;
byte[] buf = encoding.GetBytes(str);
await s.WriteValueUnmanagedAsync(buf.Length, token);
await s.WriteValueUnmanagedAsync(code,token);
await s.WriteAllAsync(buf,token);
}
public static string ReadString(this Stream s, Encoding encoding = null)
{
int len = s.ReadValueUnmanaged<int>();
int code = s.ReadValueUnmanaged<int>();
byte[] buf = s.ReadNew(len);
if (encoding == null)
encoding = Encoding.GetEncoding(code);
return encoding.GetString(buf);
}
public static async Task<string> ReadStringAsync(this Stream s, CancellationToken token = default)
{
int len = await s.ReadValueUnmanagedAsync<int>(token);
int code = await s.ReadValueUnmanagedAsync<int>(token);
byte[] buf = await s.ReadNewAsync(len, token);
var encoding = Encoding.GetEncoding(code);
return encoding.GetString(buf);
}
public static async Task<string> ReadStringAsync(this Stream s, Encoding encoding, CancellationToken token = default)
{
int len = await s.ReadValueUnmanagedAsync<int>(token);
await s.ReadValueUnmanagedAsync<int>(token);
byte[] buf = await s.ReadNewAsync(len, token);
return encoding.GetString(buf);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe T ReadValueUnmanaged<T>(this Stream s) where T : unmanaged
{
T output;
byte[] buffer = new byte[sizeof(T)];
s.Read(buffer, 0, buffer.Length);
fixed (byte* ptr = buffer)
{
output = *(T*)ptr;
}
return output;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<T> ReadValueUnmanagedAsync<T>(this Stream s, CancellationToken token=default) where T : unmanaged
{
T output;
int len;
unsafe
{
len = sizeof(T);
}
byte[] buffer = new byte[len];
await s.ReadAsync(buffer, 0, buffer.Length, token);
unsafe
{
fixed (byte* ptr = buffer)
{
output = *(T*)ptr;
}
}
return output;
}
}
}