Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 3fe17b9

Browse files
author
John Luo
committed
Merge branch 'release/2.2'
2 parents b2d53bd + 800c79c commit 3fe17b9

File tree

1 file changed

+86
-12
lines changed

1 file changed

+86
-12
lines changed

src/Microsoft.AspNetCore.WebUtilities/HttpResponseStreamWriter.cs

+86-12
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
using System;
55
using System.Buffers;
6+
using System.Diagnostics;
67
using System.IO;
8+
using System.Runtime.CompilerServices;
79
using System.Text;
810
using System.Threading.Tasks;
911

@@ -150,33 +152,65 @@ public override void Write(string value)
150152
}
151153
}
152154

153-
public override async Task WriteAsync(char value)
155+
public override Task WriteAsync(char value)
154156
{
155157
if (_disposed)
156158
{
157-
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
159+
return GetObjectDisposedTask();
158160
}
159161

160162
if (_charBufferCount == _charBufferSize)
161163
{
162-
await FlushInternalAsync(flushEncoder: false);
164+
return WriteAsyncAwaited(value);
165+
}
166+
else
167+
{
168+
// Enough room in buffer, no need to go async
169+
_charBuffer[_charBufferCount] = value;
170+
_charBufferCount++;
171+
return Task.CompletedTask;
163172
}
173+
}
174+
175+
private async Task WriteAsyncAwaited(char value)
176+
{
177+
Debug.Assert(_charBufferCount == _charBufferSize);
178+
179+
await FlushInternalAsync(flushEncoder: false);
164180

165181
_charBuffer[_charBufferCount] = value;
166182
_charBufferCount++;
167183
}
168184

169-
public override async Task WriteAsync(char[] values, int index, int count)
185+
public override Task WriteAsync(char[] values, int index, int count)
170186
{
171187
if (_disposed)
172188
{
173-
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
189+
return GetObjectDisposedTask();
174190
}
175191

176-
if (values == null)
192+
if (values == null || count == 0)
177193
{
178-
return;
194+
return Task.CompletedTask;
195+
}
196+
197+
var remaining = _charBufferSize - _charBufferCount;
198+
if (remaining >= count)
199+
{
200+
// Enough room in buffer, no need to go async
201+
CopyToCharBuffer(values, ref index, ref count);
202+
return Task.CompletedTask;
179203
}
204+
else
205+
{
206+
return WriteAsyncAwaited(values, index, count);
207+
}
208+
}
209+
210+
private async Task WriteAsyncAwaited(char[] values, int index, int count)
211+
{
212+
Debug.Assert(count > 0);
213+
Debug.Assert(_charBufferSize - _charBufferCount > count);
180214

181215
while (count > 0)
182216
{
@@ -186,22 +220,43 @@ public override async Task WriteAsync(char[] values, int index, int count)
186220
}
187221

188222
CopyToCharBuffer(values, ref index, ref count);
223+
Debug.Assert(count == 0);
189224
}
190225
}
191226

192-
public override async Task WriteAsync(string value)
227+
public override Task WriteAsync(string value)
193228
{
194229
if (_disposed)
195230
{
196-
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
231+
return GetObjectDisposedTask();
197232
}
198233

199-
if (value == null)
234+
var count = value?.Length ?? 0;
235+
if (count == 0)
200236
{
201-
return;
237+
return Task.CompletedTask;
202238
}
203239

240+
var remaining = _charBufferSize - _charBufferCount;
241+
if (remaining >= count)
242+
{
243+
// Enough room in buffer, no need to go async
244+
CopyToCharBuffer(value);
245+
return Task.CompletedTask;
246+
}
247+
else
248+
{
249+
return WriteAsyncAwaited(value);
250+
}
251+
}
252+
253+
private async Task WriteAsyncAwaited(string value)
254+
{
204255
var count = value.Length;
256+
257+
Debug.Assert(count > 0);
258+
Debug.Assert(_charBufferSize - _charBufferCount < count);
259+
205260
var index = 0;
206261
while (count > 0)
207262
{
@@ -231,7 +286,7 @@ public override Task FlushAsync()
231286
{
232287
if (_disposed)
233288
{
234-
throw new ObjectDisposedException(nameof(HttpResponseStreamWriter));
289+
return GetObjectDisposedTask();
235290
}
236291

237292
return FlushInternalAsync(flushEncoder: true);
@@ -306,6 +361,19 @@ private async Task FlushInternalAsync(bool flushEncoder)
306361
}
307362
}
308363

364+
private void CopyToCharBuffer(string value)
365+
{
366+
Debug.Assert(_charBufferSize - _charBufferCount >= value.Length);
367+
368+
value.CopyTo(
369+
sourceIndex: 0,
370+
destination: _charBuffer,
371+
destinationIndex: _charBufferCount,
372+
count: value.Length);
373+
374+
_charBufferCount += value.Length;
375+
}
376+
309377
private void CopyToCharBuffer(string value, ref int index, ref int count)
310378
{
311379
var remaining = Math.Min(_charBufferSize - _charBufferCount, count);
@@ -336,5 +404,11 @@ private void CopyToCharBuffer(char[] values, ref int index, ref int count)
336404
index += remaining;
337405
count -= remaining;
338406
}
407+
408+
[MethodImpl(MethodImplOptions.NoInlining)]
409+
private static Task GetObjectDisposedTask()
410+
{
411+
return Task.FromException(new ObjectDisposedException(nameof(HttpResponseStreamWriter)));
412+
}
339413
}
340414
}

0 commit comments

Comments
 (0)