namespace System.IO
{
///
/// Adding .NET CopyTo as extension method for .NET 3.5 support
///
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
///
/// Implementation to copy a fixed amount of data to self in stream
///
/// The stream to modify
/// Offset into stream to copy
/// Amount of stream to copy
/// Size of array to use for each copy
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
}
}
}
}