This repository was archived by the owner on Dec 18, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 446
/
Copy pathUtf8BufferTextReader.cs
93 lines (80 loc) · 2.58 KB
/
Utf8BufferTextReader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.AspNetCore.SignalR.Internal
{
internal sealed class Utf8BufferTextReader : TextReader
{
private readonly Decoder _decoder;
private ReadOnlySequence<byte> _utf8Buffer;
[ThreadStatic]
private static Utf8BufferTextReader _cachedInstance;
#if DEBUG
private bool _inUse;
#endif
public Utf8BufferTextReader()
{
_decoder = Encoding.UTF8.GetDecoder();
}
public static Utf8BufferTextReader Get(in ReadOnlySequence<byte> utf8Buffer)
{
var reader = _cachedInstance;
if (reader == null)
{
reader = new Utf8BufferTextReader();
}
// Taken off the thread static
_cachedInstance = null;
#if DEBUG
if (reader._inUse)
{
throw new InvalidOperationException("The reader wasn't returned!");
}
reader._inUse = true;
#endif
reader.SetBuffer(utf8Buffer);
return reader;
}
public static void Return(Utf8BufferTextReader reader)
{
_cachedInstance = reader;
#if DEBUG
reader._inUse = false;
#endif
}
public void SetBuffer(in ReadOnlySequence<byte> utf8Buffer)
{
_utf8Buffer = utf8Buffer;
_decoder.Reset();
}
public override int Read(char[] buffer, int index, int count)
{
if (_utf8Buffer.IsEmpty)
{
return 0;
}
var source = _utf8Buffer.First.Span;
var bytesUsed = 0;
var charsUsed = 0;
#if NETCOREAPP3_0
var destination = new Span<char>(buffer, index, count);
_decoder.Convert(source, destination, false, out bytesUsed, out charsUsed, out var completed);
#else
unsafe
{
fixed (char* destinationChars = &buffer[index])
fixed (byte* sourceBytes = &MemoryMarshal.GetReference(source))
{
_decoder.Convert(sourceBytes, source.Length, destinationChars, count, false, out bytesUsed, out charsUsed, out var completed);
}
}
#endif
_utf8Buffer = _utf8Buffer.Slice(bytesUsed);
return charsUsed;
}
}
}