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
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;
|
|
}
|
|
}
|
|
}
|