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.4 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Runtime.InteropServices;
  7. using System.Security.Permissions;
  8. using System.Text;
  9. using System.Threading;
  10. using System.Threading.Tasks;
  11. namespace Net3_Proxy
  12. {
  13. public static class Extensions
  14. {
  15. public static T GetCustomAttribute<T>(this ParameterInfo element) where T : Attribute
  16. => (T)GetCustomAttribute(element, typeof(T));
  17. public static Attribute GetCustomAttribute(this MemberInfo element, Type attributeType)
  18. => Attribute.GetCustomAttribute(element, attributeType);
  19. public static Attribute GetCustomAttribute(this ParameterInfo element, Type attributeType)
  20. => Attribute.GetCustomAttribute(element, attributeType);
  21. public static StringBuilder Clear(this StringBuilder sb)
  22. => sb.Remove(0, sb.Length);
  23. public static bool HasFlag<E>(this E e, E o) where E : Enum
  24. {
  25. var ei = Convert.ToUInt64(e);
  26. var oi = Convert.ToUInt64(o);
  27. return (ei & oi) == oi;
  28. }
  29. }
  30. public static class DirectoryInfoExtensions
  31. {
  32. public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self)
  33. {
  34. return self.EnumerateFiles("*", SearchOption.TopDirectoryOnly);
  35. }
  36. public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self, string searchPattern)
  37. {
  38. return self.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly);
  39. }
  40. public static IEnumerable<FileInfo> EnumerateFiles(this DirectoryInfo self, string searchPattern, SearchOption searchOption)
  41. {
  42. if (searchPattern == null)
  43. {
  44. throw new ArgumentNullException(nameof(searchPattern));
  45. }
  46. return CreateEnumerateFilesIterator(self, searchPattern, searchOption);
  47. }
  48. private static IEnumerable<FileInfo> CreateEnumerateFilesIterator(DirectoryInfo self, string searchPattern, SearchOption searchOption)
  49. {
  50. foreach (string fileName in Directory.GetFiles(self.FullName, searchPattern, searchOption))
  51. yield return new FileInfo(fileName);
  52. yield break;
  53. }
  54. }
  55. public static class StreamExtensions
  56. {
  57. [ComVisible(false)]
  58. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  59. public static Task CopyToAsync(this Stream src, Stream destination) => CopyToAsync(src, destination, 81920);
  60. [ComVisible(false)]
  61. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  62. public static Task CopyToAsync(this Stream src, Stream destination, int bufferSize) => CopyToAsync(src, destination, bufferSize, CancellationToken.None);
  63. [ComVisible(false)]
  64. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  65. public static Task CopyToAsync(this Stream src, Stream destination, int bufferSize, CancellationToken cancellationToken)
  66. {
  67. if (destination == null)
  68. {
  69. throw new ArgumentNullException(nameof(destination));
  70. }
  71. if (bufferSize <= 0)
  72. {
  73. throw new ArgumentOutOfRangeException(nameof(bufferSize), "Positive number required.");
  74. }
  75. if (!src.CanRead && !src.CanWrite)
  76. {
  77. throw new ObjectDisposedException(null, "Cannot access a closed Stream.");
  78. }
  79. if (!destination.CanRead && !destination.CanWrite)
  80. {
  81. throw new ObjectDisposedException("destination", "Cannot access a closed Stream.");
  82. }
  83. if (!src.CanRead)
  84. {
  85. throw new NotSupportedException("Stream does not support reading.");
  86. }
  87. if (!destination.CanWrite)
  88. {
  89. throw new NotSupportedException("Stream does not support writing.");
  90. }
  91. return CopyToAsyncInternal(src, destination, bufferSize, cancellationToken);
  92. }
  93. private static async Task CopyToAsyncInternal(Stream src, Stream destination, int bufferSize, CancellationToken cancellationToken)
  94. {
  95. byte[] buffer = new byte[bufferSize];
  96. int bytesRead;
  97. while ((bytesRead = await src.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) != 0)
  98. {
  99. await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken);
  100. }
  101. }
  102. [ComVisible(false)]
  103. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  104. public static Task<int> ReadAsync(this Stream src, byte[] buffer, int offset, int count)
  105. {
  106. return ReadAsync(src, buffer, offset, count, CancellationToken.None);
  107. }
  108. [ComVisible(false)]
  109. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  110. public static Task<int> ReadAsync(this Stream src, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  111. {
  112. if (!cancellationToken.IsCancellationRequested)
  113. {
  114. return BeginEndReadAsync(src, buffer, offset, count);
  115. }
  116. return new Task<int>(() => 0, cancellationToken);
  117. }
  118. private static Task<int> BeginEndReadAsync(Stream src, byte[] buffer, int offset, int count)
  119. => Task<int>.Factory.FromAsync(
  120. (byte[] buffer_, int offset_, int count_, AsyncCallback callback, object state) =>
  121. src.BeginRead(buffer_, offset_, count_, callback, state),
  122. (IAsyncResult asyncResult) => src.EndRead(asyncResult),
  123. buffer,
  124. offset,
  125. count,
  126. new object());
  127. [ComVisible(false)]
  128. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  129. public static Task WriteAsync(this Stream src, byte[] buffer, int offset, int count)
  130. {
  131. return WriteAsync(src, buffer, offset, count, CancellationToken.None);
  132. }
  133. [ComVisible(false)]
  134. [HostProtection(SecurityAction.LinkDemand, ExternalThreading = true)]
  135. public static Task WriteAsync(this Stream src, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
  136. {
  137. if (!cancellationToken.IsCancellationRequested)
  138. {
  139. return BeginEndWriteAsync(src, buffer, offset, count);
  140. }
  141. return new Task<int>(() => 0, cancellationToken);
  142. }
  143. private static Task BeginEndWriteAsync(Stream src, byte[] buffer, int offset, int count)
  144. => Task.Factory.FromAsync(
  145. (byte[] buffer_, int offset_, int count_, AsyncCallback callback, object state) =>
  146. src.BeginWrite(buffer_, offset_, count_, callback, state),
  147. (IAsyncResult asyncResult) => src.EndWrite(asyncResult),
  148. buffer,
  149. offset,
  150. count,
  151. new object());
  152. }
  153. public static class SemaphoreSlimExtesnions
  154. { // TODO: finish the WaitAsync members
  155. /*public static Task WaitAsync(this SemaphoreSlim self)
  156. {
  157. return null;
  158. }*/
  159. }
  160. }