Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit e45523d

Browse files
jkotasstephentoub
authored andcommitted
Replace ValueStringBuilder.set_Length with indexer (#27274)
Indexer that let's you see and edit the content of the pending string is more efficient and flexible. Fixes #26643
1 parent 5a57de7 commit e45523d

File tree

5 files changed

+26
-41
lines changed

5 files changed

+26
-41
lines changed

src/Common/src/CoreLib/System/Collections/Generic/ValueListBuilder.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ public ValueListBuilder(Span<T> initialSpan)
2323

2424
public int Length => _pos;
2525

26+
public ref T this[int index]
27+
{
28+
get
29+
{
30+
Debug.Assert(index < _pos);
31+
return ref _span[index];
32+
}
33+
}
34+
2635
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2736
public void Append(T item)
2837
{

src/Common/src/CoreLib/System/Text/ValueStringBuilder.cs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,21 @@ public ValueStringBuilder(Span<char> initialBuffer)
2121
_pos = 0;
2222
}
2323

24-
public int Length
24+
public int Length => _pos;
25+
26+
public ref char this[int index]
2527
{
26-
get => _pos;
27-
set
28-
{
29-
int delta = value - _pos;
30-
if (delta > 0)
31-
{
32-
Append('\0', delta);
33-
}
34-
else
35-
{
36-
_pos = value;
37-
}
28+
get
29+
{
30+
Debug.Assert(index < _pos);
31+
return ref _chars[index];
3832
}
3933
}
4034

4135
public override string ToString()
4236
{
4337
var s = new string(_chars.Slice(0, _pos));
44-
Clear();
38+
Dispose();
4539
return s;
4640
}
4741

@@ -50,13 +44,13 @@ public bool TryCopyTo(Span<char> destination, out int charsWritten)
5044
if (_chars.Slice(0, _pos).TryCopyTo(destination))
5145
{
5246
charsWritten = _pos;
53-
Clear();
47+
Dispose();
5448
return true;
5549
}
5650
else
5751
{
5852
charsWritten = 0;
59-
Clear();
53+
Dispose();
6054
return false;
6155
}
6256
}
@@ -185,7 +179,7 @@ private void Grow(int requiredAdditionalCapacity)
185179
}
186180

187181
[MethodImpl(MethodImplOptions.AggressiveInlining)]
188-
private void Clear()
182+
public void Dispose()
189183
{
190184
char[] toReturn = _arrayToReturnToPool;
191185
this = default; // for safety, to avoid using pooled array if this instance is erroneously appended to again

src/Common/tests/Tests/System/Text/ValueStringBuilderTests.cs

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -214,31 +214,16 @@ public void TryCopyTo_ClearsBuilder_ThenReusable()
214214
}
215215

216216
[Fact]
217-
public unsafe void Length_Growing_SetsNulls()
217+
public unsafe void Indexer()
218218
{
219219
const string Text1 = "foobar";
220220
var vsb = new ValueStringBuilder();
221221

222-
// Shrink then grow within capacity
223222
vsb.Append(Text1);
224-
Assert.Equal(Text1.Length, vsb.Length);
225-
vsb.Length = 3;
226-
Assert.Equal(3, vsb.Length);
227-
vsb.Length = 6;
228-
Assert.Equal(6, vsb.Length);
229-
Assert.Equal("foo\0\0\0", vsb.ToString());
230-
231-
// Grow over capacity
232-
const string Text2 = "bar";
233-
Span<char> stackSpace = stackalloc char[Text2.Length];
234-
var vsb2 = new ValueStringBuilder(stackSpace);
235-
Assert.Equal(0, vsb2.Length);
236-
vsb2.Append(Text2);
237-
Assert.True(Text2.AsReadOnlySpan().SequenceEqual(stackSpace), "existing stack buffer should have been used");
238-
Assert.Equal(Text2.Length, vsb2.Length);
239-
vsb2.Length = 6;
240-
Assert.Equal(6, vsb2.Length);
241-
Assert.Equal("bar\0\0\0", vsb2.ToString());
223+
224+
Assert.Equal(vsb[3], 'b');
225+
vsb[3] = 'c';
226+
Assert.Equal(vsb[3], 'c');
242227
}
243228
}
244229
}

src/System.IO.FileSystem/src/System/IO/Enumeration/FileSystemName.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ public static string TranslateDosExpression(string expression)
4646
modified = true;
4747
if (i > 1 && i == length - 1 && expression[i - 1] == '*')
4848
{
49-
sb.Length--;
50-
sb.Append('<'); // DOS_STAR (ends in *.)
49+
sb[sb.Length - 1] = '<'; // DOS_STAR (ends in *.)
5150
}
5251
else if (i < length - 1 && (expression[i + 1] == '?' || expression[i + 1] == '*'))
5352
{

src/System.Text.RegularExpressions/src/System/Text/RegularExpressions/ValueListBuilder.Pop.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ namespace System.Collections.Generic
1111
/// </summary>
1212
internal ref partial struct ValueListBuilder<T>
1313
{
14-
public ref T this[int index] => ref _span[index];
15-
1614
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1715
public T Pop()
1816
{

0 commit comments

Comments
 (0)