Improve writing single characters with UTF8 text writer (#1814)
This commit is contained in:
parent
e6e45cea05
commit
ca161e9bc8
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
|
@ -86,44 +87,49 @@ namespace Microsoft.AspNetCore.SignalR.Internal.Protocol
|
||||||
|
|
||||||
public override void Write(char value)
|
public override void Write(char value)
|
||||||
{
|
{
|
||||||
var destination = GetBuffer();
|
|
||||||
|
|
||||||
if (value <= 127)
|
if (value <= 127)
|
||||||
{
|
{
|
||||||
destination[0] = (byte)value;
|
EnsureBuffer();
|
||||||
|
|
||||||
|
// Only need to set one byte
|
||||||
|
// Avoid Memory<T>.Slice overhead for perf
|
||||||
|
_memory.Span[_memoryUsed] = (byte)value;
|
||||||
_memoryUsed++;
|
_memoryUsed++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Json.NET only writes ASCII characters by themselves, e.g. {}[], etc
|
WriteMultiByteChar(value);
|
||||||
// this should be an exceptional case
|
|
||||||
var bytesUsed = 0;
|
|
||||||
var charsUsed = 0;
|
|
||||||
unsafe
|
|
||||||
{
|
|
||||||
#if NETCOREAPP2_1
|
|
||||||
_encoder.Convert(new Span<char>(&value, 1), destination, false, out charsUsed, out bytesUsed, out _);
|
|
||||||
#else
|
|
||||||
fixed (byte* destinationBytes = &MemoryMarshal.GetReference(destination))
|
|
||||||
{
|
|
||||||
_encoder.Convert(&value, 1, destinationBytes, destination.Length, false, out charsUsed, out bytesUsed, out _);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
Debug.Assert(charsUsed == 1);
|
|
||||||
|
|
||||||
if (bytesUsed > 0)
|
|
||||||
{
|
|
||||||
_memoryUsed += bytesUsed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unsafe void WriteMultiByteChar(char value)
|
||||||
|
{
|
||||||
|
var destination = GetBuffer();
|
||||||
|
|
||||||
|
// Json.NET only writes ASCII characters by themselves, e.g. {}[], etc
|
||||||
|
// this should be an exceptional case
|
||||||
|
var bytesUsed = 0;
|
||||||
|
var charsUsed = 0;
|
||||||
|
#if NETCOREAPP2_1
|
||||||
|
_encoder.Convert(new Span<char>(&value, 1), destination, false, out charsUsed, out bytesUsed, out _);
|
||||||
|
#else
|
||||||
|
fixed (byte* destinationBytes = &MemoryMarshal.GetReference(destination))
|
||||||
|
{
|
||||||
|
_encoder.Convert(&value, 1, destinationBytes, destination.Length, false, out charsUsed, out bytesUsed, out _);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Debug.Assert(charsUsed == 1);
|
||||||
|
|
||||||
|
_memoryUsed += bytesUsed;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Write(string value)
|
public override void Write(string value)
|
||||||
{
|
{
|
||||||
WriteInternal(value.AsSpan());
|
WriteInternal(value.AsSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private Span<byte> GetBuffer()
|
private Span<byte> GetBuffer()
|
||||||
{
|
{
|
||||||
EnsureBuffer();
|
EnsureBuffer();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue