Merge branch 'release/2.2'

This commit is contained in:
John Luo 2018-10-10 18:14:38 -07:00
commit 3fe17b9faf
1 changed files with 86 additions and 12 deletions

View File

@ -3,7 +3,9 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -150,34 +152,66 @@ namespace Microsoft.AspNetCore.WebUtilities
} }
} }
public override async Task WriteAsync(char value) public override Task WriteAsync(char value)
{ {
if (_disposed) if (_disposed)
{ {
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter)); return GetObjectDisposedTask();
} }
if (_charBufferCount == _charBufferSize) if (_charBufferCount == _charBufferSize)
{ {
await FlushInternalAsync(flushEncoder: false); return WriteAsyncAwaited(value);
} }
else
{
// Enough room in buffer, no need to go async
_charBuffer[_charBufferCount] = value;
_charBufferCount++;
return Task.CompletedTask;
}
}
private async Task WriteAsyncAwaited(char value)
{
Debug.Assert(_charBufferCount == _charBufferSize);
await FlushInternalAsync(flushEncoder: false);
_charBuffer[_charBufferCount] = value; _charBuffer[_charBufferCount] = value;
_charBufferCount++; _charBufferCount++;
} }
public override async Task WriteAsync(char[] values, int index, int count) public override Task WriteAsync(char[] values, int index, int count)
{ {
if (_disposed) if (_disposed)
{ {
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter)); return GetObjectDisposedTask();
} }
if (values == null) if (values == null || count == 0)
{ {
return; return Task.CompletedTask;
} }
var remaining = _charBufferSize - _charBufferCount;
if (remaining >= count)
{
// Enough room in buffer, no need to go async
CopyToCharBuffer(values, ref index, ref count);
return Task.CompletedTask;
}
else
{
return WriteAsyncAwaited(values, index, count);
}
}
private async Task WriteAsyncAwaited(char[] values, int index, int count)
{
Debug.Assert(count > 0);
Debug.Assert(_charBufferSize - _charBufferCount > count);
while (count > 0) while (count > 0)
{ {
if (_charBufferCount == _charBufferSize) if (_charBufferCount == _charBufferSize)
@ -186,22 +220,43 @@ namespace Microsoft.AspNetCore.WebUtilities
} }
CopyToCharBuffer(values, ref index, ref count); CopyToCharBuffer(values, ref index, ref count);
Debug.Assert(count == 0);
} }
} }
public override async Task WriteAsync(string value) public override Task WriteAsync(string value)
{ {
if (_disposed) if (_disposed)
{ {
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter)); return GetObjectDisposedTask();
} }
if (value == null) var count = value?.Length ?? 0;
if (count == 0)
{ {
return; return Task.CompletedTask;
} }
var remaining = _charBufferSize - _charBufferCount;
if (remaining >= count)
{
// Enough room in buffer, no need to go async
CopyToCharBuffer(value);
return Task.CompletedTask;
}
else
{
return WriteAsyncAwaited(value);
}
}
private async Task WriteAsyncAwaited(string value)
{
var count = value.Length; var count = value.Length;
Debug.Assert(count > 0);
Debug.Assert(_charBufferSize - _charBufferCount < count);
var index = 0; var index = 0;
while (count > 0) while (count > 0)
{ {
@ -231,7 +286,7 @@ namespace Microsoft.AspNetCore.WebUtilities
{ {
if (_disposed) if (_disposed)
{ {
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter)); return GetObjectDisposedTask();
} }
return FlushInternalAsync(flushEncoder: true); return FlushInternalAsync(flushEncoder: true);
@ -306,6 +361,19 @@ namespace Microsoft.AspNetCore.WebUtilities
} }
} }
private void CopyToCharBuffer(string value)
{
Debug.Assert(_charBufferSize - _charBufferCount >= value.Length);
value.CopyTo(
sourceIndex: 0,
destination: _charBuffer,
destinationIndex: _charBufferCount,
count: value.Length);
_charBufferCount += value.Length;
}
private void CopyToCharBuffer(string value, ref int index, ref int count) private void CopyToCharBuffer(string value, ref int index, ref int count)
{ {
var remaining = Math.Min(_charBufferSize - _charBufferCount, count); var remaining = Math.Min(_charBufferSize - _charBufferCount, count);
@ -336,5 +404,11 @@ namespace Microsoft.AspNetCore.WebUtilities
index += remaining; index += remaining;
count -= remaining; count -= remaining;
} }
[MethodImpl(MethodImplOptions.NoInlining)]
private static Task GetObjectDisposedTask()
{
return Task.FromException(new ObjectDisposedException(nameof(HttpResponseStreamWriter)));
}
} }
} }