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.
 
 
 
 

182 lines
7.2 KiB

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Net3_Proxy
{
public static class Extensions
{
public static T GetCustomAttribute<T>(this ParameterInfo element) where T : Attribute
=> (T)GetCustomAttribute(element, typeof(T));
public static Attribute GetCustomAttribute(this MemberInfo element, Type attributeType)
=> Attribute.GetCustomAttribute(element, attributeType);
public static Attribute GetCustomAttribute(this ParameterInfo element, Type attributeType)
=> Attribute.GetCustomAttribute(element, attributeType);
public static StringBuilder Clear(this StringBuilder sb)
=> sb.Remove(0, sb.Length);
public static bool HasFlag<E>(this E e, E o) where E : Enum
{
var ei = Convert.ToUInt64(e);
var oi = Convert.ToUInt64(o);
return (ei & oi) == oi;
}
}
public static class DirectoryInfoExtensions
{
public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self)
{
return self.EnumerateFiles("*", SearchOption.TopDirectoryOnly);
}
public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self, string searchPattern)
{
return self.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly);
}
public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self, string searchPattern, SearchOption searchOption)
{
if (searchPattern == null)
{
throw new ArgumentNullException("searchPattern");
}
return CreateEnumerateFilesIterator(self, searchPattern, searchOption);
}
private static IEnumerable<FileInfo> CreateEnumerateFilesIterator(DirectoryInfo self, string searchPattern, SearchOption searchOption)
{
foreach (string fileName in Directory.GetFiles(self.FullName, searchPattern, searchOption))
yield return new FileInfo(fileName);
yield break;
}
}
public static class StreamExtensions
{
[ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public static Task CopyToAsync(this Stream src, Stream destination) => CopyToAsync(src, destination, 81920);
[ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public static Task CopyToAsync(this Stream src, Stream destination, int bufferSize) => CopyToAsync(src, destination, bufferSize, CancellationToken.None);
[ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public static Task CopyToAsync(this Stream src, Stream destination, int bufferSize, CancellationToken cancellationToken)
{
if (destination == null)
{
throw new ArgumentNullException("destination");
}
if (bufferSize <= 0)
{
throw new ArgumentOutOfRangeException("bufferSize", "Positive number required.");
}
if (!src.CanRead && !src.CanWrite)
{
throw new ObjectDisposedException(null, "Cannot access a closed Stream.");
}
if (!destination.CanRead && !destination.CanWrite)
{
throw new ObjectDisposedException("destination", "Cannot access a closed Stream.");
}
if (!src.CanRead)
{
throw new NotSupportedException("Stream does not support reading.");
}
if (!destination.CanWrite)
{
throw new NotSupportedException("Stream does not support writing.");
}
return CopyToAsyncInternal(src, destination, bufferSize, cancellationToken);
}
private static async Task CopyToAsyncInternal(Stream src, Stream destination, int bufferSize, CancellationToken cancellationToken)
{
byte[] buffer = new byte[bufferSize];
int bytesRead;
while ((bytesRead = await src.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) != 0)
{
await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken);
}
}
[ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public static Task<int> ReadAsync(this Stream src, byte[] buffer, int offset, int count)
{
return ReadAsync(src, buffer, offset, count, CancellationToken.None);
}
[ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public static Task<int> ReadAsync(this Stream src, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (!cancellationToken.IsCancellationRequested)
{
return BeginEndReadAsync(src, buffer, offset, count);
}
return new Task<int>(() => 0, cancellationToken);
}
private static Task<int> BeginEndReadAsync(Stream src, byte[] buffer, int offset, int count)
=> Task<int>.Factory.FromAsync(
(byte[] buffer_, int offset_, int count_, AsyncCallback callback, object state) =>
src.BeginRead(buffer_, offset_, count_, callback, state),
(IAsyncResult asyncResult) => src.EndRead(asyncResult),
buffer,
offset,
count,
new object());
[ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public static Task WriteAsync(this Stream src, byte[] buffer, int offset, int count)
{
return WriteAsync(src, buffer, offset, count, CancellationToken.None);
}
[ComVisible(false)]
[HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
public static Task WriteAsync(this Stream src, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (!cancellationToken.IsCancellationRequested)
{
return BeginEndWriteAsync(src, buffer, offset, count);
}
return new Task<int>(() => 0, cancellationToken);
}
private static Task BeginEndWriteAsync(Stream src, byte[] buffer, int offset, int count)
=> Task.Factory.FromAsync(
(byte[] buffer_, int offset_, int count_, AsyncCallback callback, object state) =>
src.BeginWrite(buffer_, offset_, count_, callback, state),
(IAsyncResult asyncResult) => src.EndWrite(asyncResult),
buffer,
offset,
count,
new object());
}
public static class SemaphoreSlimExtesnions
{ // TODO: finish the WaitAsync members
/*public static Task WaitAsync(this SemaphoreSlim self)
{
return null;
}*/
}
}