diff options
author | Stephen Toub <stoub@microsoft.com> | 2017-09-29 15:39:40 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-29 15:39:40 +0300 |
commit | a410be2defea87b9d4a9926efa896c35429e31b9 (patch) | |
tree | c14ddca863c5174cd1ef69fcff63bb5b6f677967 | |
parent | 55c9db39ce33698a5aec98fd5bea2a0b9c835ab8 (diff) | |
parent | 3c53151d76da06a36360963361b0485827c75a9d (diff) |
Merge pull request #4634 from khellang/copy-to-async-buffer-size
Added CopyToAsync overload using default buffer size
-rw-r--r-- | src/System.Private.CoreLib/src/System/IO/Stream.cs | 83 |
1 files changed, 36 insertions, 47 deletions
diff --git a/src/System.Private.CoreLib/src/System/IO/Stream.cs b/src/System.Private.CoreLib/src/System/IO/Stream.cs index b5e16d9ac..4b6068bb7 100644 --- a/src/System.Private.CoreLib/src/System/IO/Stream.cs +++ b/src/System.Private.CoreLib/src/System/IO/Stream.cs @@ -95,36 +95,7 @@ namespace System.IO public Task CopyToAsync(Stream destination) { - int bufferSize = DefaultCopyBufferSize; - - if (CanSeek) - { - long length = Length; - long position = Position; - if (length <= position) // Handles negative overflows - { - // If we go down this branch, it means there are - // no bytes left in this stream. - - // Ideally we would just return Task.CompletedTask here, - // but CopyToAsync(Stream, int, CancellationToken) was already - // virtual at the time this optimization was introduced. So - // if it does things like argument validation (checking if destination - // is null and throwing an exception), then await fooStream.CopyToAsync(null) - // would no longer throw if there were no bytes left. On the other hand, - // we also can't roll our own argument validation and return Task.CompletedTask, - // because it would be a breaking change if the stream's override didn't throw before, - // or in a different order. So for simplicity, we just set the bufferSize to 1 - // (not 0 since the default implementation throws for 0) and forward to the virtual method. - bufferSize = 1; - } - else - { - long remaining = length - position; - if (remaining > 0) // In the case of a positive overflow, stick to the default size - bufferSize = (int)Math.Min(bufferSize, remaining); - } - } + int bufferSize = GetCopyBufferSize(); return CopyToAsync(destination, bufferSize); } @@ -134,6 +105,13 @@ namespace System.IO return CopyToAsync(destination, bufferSize, CancellationToken.None); } + public Task CopyToAsync(Stream destination, CancellationToken cancellationToken) + { + int bufferSize = GetCopyBufferSize(); + + return CopyToAsync(destination, bufferSize, cancellationToken); + } + public virtual Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) { StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); @@ -162,6 +140,25 @@ namespace System.IO // the current position. public void CopyTo(Stream destination) { + int bufferSize = GetCopyBufferSize(); + + CopyTo(destination, bufferSize); + } + + public virtual void CopyTo(Stream destination, int bufferSize) + { + StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); + + byte[] buffer = new byte[bufferSize]; + int read; + while ((read = Read(buffer, 0, buffer.Length)) != 0) + { + destination.Write(buffer, 0, read); + } + } + + private int GetCopyBufferSize() + { int bufferSize = DefaultCopyBufferSize; if (CanSeek) @@ -170,32 +167,24 @@ namespace System.IO long position = Position; if (length <= position) // Handles negative overflows { - // No bytes left in stream - // Call the other overload with a bufferSize of 1, - // in case it's made virtual in the future + // There are no bytes left in the stream to copy. + // However, because CopyTo{Async} is virtual, we need to + // ensure that any override is still invoked to provide its + // own validation, so we use the smallest legal buffer size here. bufferSize = 1; } else { long remaining = length - position; - if (remaining > 0) // In the case of a positive overflow, stick to the default size + if (remaining > 0) + { + // In the case of a positive overflow, stick to the default size bufferSize = (int)Math.Min(bufferSize, remaining); + } } } - CopyTo(destination, bufferSize); - } - - public virtual void CopyTo(Stream destination, int bufferSize) - { - StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize); - - byte[] buffer = new byte[bufferSize]; - int read; - while ((read = Read(buffer, 0, buffer.Length)) != 0) - { - destination.Write(buffer, 0, read); - } + return bufferSize; } public virtual void Close() |