Files
2025-11-30 08:35:03 +02:00

66 lines
2.2 KiB
C#

namespace System.IO
{
/// <summary>
/// Adding .NET CopyTo as extension method for .NET 3.5 support
/// </summary>
internal static class StreamExtensions
{
// We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
// The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
// improvement in Copy performance.
private const int _DefaultCopyBufferSize = 81920;
private static readonly byte[] _CopyBuffer = new byte[_DefaultCopyBufferSize];
#if !NETFX_CORE
public static void CopyTo(this Stream source, Stream destination)
{
int highwaterMark = 0;
try
{
int read;
while ((read = source.Read(_CopyBuffer, 0, _CopyBuffer.Length)) != 0)
{
if (read > highwaterMark) highwaterMark = read;
destination.Write(_CopyBuffer, 0, read);
}
}
finally
{
Array.Clear(_CopyBuffer, 0, highwaterMark); // clear only the most we used
}
}
#endif
/// <summary>
/// Implementation to copy a fixed amount of data to self in stream
/// </summary>
/// <param name="source">The stream to modify</param>
/// <param name="destinationOffset">Offset into stream to copy</param>
/// <param name="amountToCopy">Amount of stream to copy</param>
/// <param name="bufferSize">Size of array to use for each copy</param>
public static void CopyToSelf(this Stream source, int destinationOffset, uint amountToCopy)
{
if (destinationOffset <= source.Position) throw new NotImplementedException("desintation offset must be larger than source offset");
int highwaterMark = 0;
long initialOffset = source.Position;
try
{
int read;
int amountToRead;
while ((source.Position = initialOffset + amountToCopy - (amountToRead = (int)Math.Min(_CopyBuffer.Length, amountToCopy))) >= 0 && (read = source.Read(_CopyBuffer, 0, amountToRead)) != 0)
{
if (read > highwaterMark) highwaterMark = read;
source.Position = destinationOffset + amountToCopy - read;
source.Write(_CopyBuffer, 0, read);
amountToCopy -= (uint)read;
}
}
finally
{
Array.Clear(_CopyBuffer, 0, highwaterMark); // clear only the most we used
}
}
}
}