Skip to content

Commit 5662202

Browse files
committed
Fixed Bug where Grow used a too small number
1 parent 794b5a0 commit 5662202

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T
66

77
## [Unreleased]
88

9+
### Changed
10+
- Fixed a bug, where in `Append` overflows the internal buffer and throws an exception
11+
- Use better struct layout to be more cache friendly
12+
913
## [1.18.4] - 2023-10-14
1014

1115
### Changed

src/LinkDotNet.StringBuilder/ValueStringBuilder.Append.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ public void Append(bool value)
1414
{
1515
// 5 is the length of the string "False"
1616
// So we can check if we have enough space in the buffer
17-
if (bufferPosition + 5 > buffer.Length)
17+
var newSize = bufferPosition + 5;
18+
if (newSize > buffer.Length)
1819
{
19-
Grow(bufferPosition);
20+
Grow(newSize);
2021
}
2122

2223
if (!value.TryFormat(buffer[bufferPosition..], out var charsWritten))
@@ -105,9 +106,10 @@ public void AppendLine(scoped ReadOnlySpan<char> str)
105106
private void AppendSpanFormattable<T>(T value, ReadOnlySpan<char> format = default, int bufferSize = 36)
106107
where T : ISpanFormattable
107108
{
108-
if (bufferSize + bufferPosition >= Capacity)
109+
var newSize = bufferSize + bufferPosition;
110+
if (newSize >= Capacity)
109111
{
110-
Grow(bufferSize + bufferPosition);
112+
Grow(newSize);
111113
}
112114

113115
if (!value.TryFormat(buffer[bufferPosition..], out var written, format, null))

src/LinkDotNet.StringBuilder/ValueStringBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace LinkDotNet.StringBuilder;
1111
/// The <see cref="ValueStringBuilder"/> is declared as ref struct which brings certain limitations with it.
1212
/// You can only use it in another ref struct or as a local variable.
1313
/// </remarks>
14-
[StructLayout(LayoutKind.Auto)]
14+
[StructLayout(LayoutKind.Sequential)]
1515
[SkipLocalsInit]
1616
public ref partial struct ValueStringBuilder
1717
{

tests/LinkDotNet.StringBuilder.Benchmarks/AppendValueTypesBenchmark.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public class AppendValueTypes
88
private const int NumberOfIterations = 25;
99

1010
[Benchmark]
11-
public string DotNetStringBuilder()
11+
public string DotNetStringBuilderAppendValue()
1212
{
1313
var builder = new System.Text.StringBuilder();
1414

@@ -24,4 +24,22 @@ public string DotNetStringBuilder()
2424

2525
return builder.ToString();
2626
}
27+
28+
[Benchmark]
29+
public string ValueStringBuilderAppendValue()
30+
{
31+
using var builder = new ValueStringBuilder();
32+
33+
for (var i = 0; i < NumberOfIterations; i++)
34+
{
35+
builder.Append(true);
36+
builder.Append(int.MaxValue);
37+
builder.Append(decimal.MaxValue);
38+
builder.Append(byte.MinValue);
39+
builder.Append(float.Epsilon);
40+
builder.Append(double.Epsilon);
41+
}
42+
43+
return builder.ToString();
44+
}
2745
}

tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Append.Tests.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,21 @@ public void GivenAStringWithWhitespace_WhenTrimIsCalled_ThenTheStringShouldBeTri
179179

180180
builder.ToString().Should().Be("Hello World");
181181
}
182+
183+
[Fact]
184+
public void GivenMultipleValues_WhenCallingAppend_NotCrashing()
185+
{
186+
using var builder = new ValueStringBuilder();
187+
builder.Append(true);
188+
builder.Append(false);
189+
builder.Append(true);
190+
builder.Append(false);
191+
builder.Append(true);
192+
builder.Append(false);
193+
builder.Append(true);
194+
195+
builder.Append(false);
196+
197+
builder.ToString().Should().NotBeNull();
198+
}
182199
}

0 commit comments

Comments
 (0)