-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathValueStringBuilder.cs
69 lines (57 loc) · 1.59 KB
/
ValueStringBuilder.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
using System.Buffers;
namespace LinkDotNet;
public ref struct ValueStringBuilder
{
private int _bufferPosition;
private Span<char> _buffer;
private char[]? _arrayFromPool;
public ValueStringBuilder()
{
_bufferPosition = 0;
_buffer = new char[32];
_arrayFromPool = null;
}
public ref char this[int index] => ref _buffer[index];
public void Append(char c)
{
if (_bufferPosition == _buffer.Length - 1)
{
Grow();
}
_buffer[_bufferPosition++] = c;
}
public void Append(ReadOnlySpan<char> str)
{
var newSize = str.Length + _bufferPosition;
if (newSize > _buffer.Length)
Grow(newSize * 2);
str.CopyTo(_buffer[_bufferPosition..]);
_bufferPosition += str.Length;
}
public void AppendLine(ReadOnlySpan<char> str)
{
Append(str);
Append(Environment.NewLine);
}
public override string ToString() => new(_buffer[.._bufferPosition]);
public void Dispose()
{
if (_arrayFromPool is not null)
{
ArrayPool<char>.Shared.Return(_arrayFromPool);
}
}
private void Grow(int capacity = 0)
{
var currentSize = _buffer.Length;
var newSize = capacity > 0 ? capacity : currentSize * 2;
var rented = ArrayPool<char>.Shared.Rent(newSize);
var oldBuffer = _arrayFromPool;
_buffer.CopyTo(rented);
_buffer = _arrayFromPool = rented;
if (oldBuffer is not null)
{
ArrayPool<char>.Shared.Return(oldBuffer);
}
}
}