Skip to content

Commit 22eaa9d

Browse files
committed
Added Insert methods
1 parent 140f5a5 commit 22eaa9d

File tree

6 files changed

+404
-50
lines changed

6 files changed

+404
-50
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T
77
## [Unreleased]
88

99
### Added
10-
- Added `Remove` method.
10+
- Added `Remove` and `Insert` methods.
1111

1212
## [0.9.1] - 2022-04-06
1313

src/LinkDotNet.StringBuilder/ValueStringBuilder.AppendSpanFormattable.cs renamed to src/LinkDotNet.StringBuilder/ValueStringBuilder.Append.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ public ref partial struct ValueStringBuilder
1111
/// <param name="value">Bool value to add.</param>
1212
public void Append(bool value) => Append(value.ToString());
1313

14+
/// <summary>
15+
/// Appends the string representation of the character to the builder.
16+
/// </summary>
17+
/// <param name="value">Integer to add.</param>
18+
public void Append(char value) => AppendSpanFormattable(value);
19+
1420
/// <summary>
1521
/// Appends the string representation of the signed byte to the builder.
1622
/// </summary>
@@ -59,6 +65,40 @@ public ref partial struct ValueStringBuilder
5965
/// <param name="value">Decimal to add.</param>
6066
public void Append(decimal value) => AppendSpanFormattable(value);
6167

68+
/// <summary>
69+
/// Appends a string to the string builder.
70+
/// </summary>
71+
/// <param name="str">String, which will be added to this builder.</param>
72+
public void Append(ReadOnlySpan<char> str)
73+
{
74+
var newSize = str.Length + bufferPosition;
75+
if (newSize > buffer.Length)
76+
{
77+
Grow(newSize * 2);
78+
}
79+
80+
str.CopyTo(buffer[bufferPosition..]);
81+
bufferPosition += str.Length;
82+
}
83+
84+
/// <summary>
85+
/// Adds the default new line separator.
86+
/// </summary>
87+
public void AppendLine()
88+
{
89+
Append(Environment.NewLine);
90+
}
91+
92+
/// <summary>
93+
/// Does the same as <see cref="Append(char)"/> but adds a newline at the end.
94+
/// </summary>
95+
/// <param name="str">String, which will be added to this builder.</param>
96+
public void AppendLine(ReadOnlySpan<char> str)
97+
{
98+
Append(str);
99+
Append(Environment.NewLine);
100+
}
101+
62102
private void AppendSpanFormattable<T>(T value)
63103
where T : ISpanFormattable
64104
{
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
namespace LinkDotNet.StringBuilder;
2+
3+
public ref partial struct ValueStringBuilder
4+
{
5+
/// <summary>
6+
/// Insert the string representation of the boolean to the builder at the given index.
7+
/// </summary>
8+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
9+
/// <param name="value">String to insert into this builder.</param>
10+
public void Insert(int index, bool value) => Insert(index, value.ToString());
11+
12+
/// <summary>
13+
/// Insert the string representation of the char to the builder at the given index.
14+
/// </summary>
15+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
16+
/// <param name="value">String to insert into this builder.</param>
17+
public void Insert(int index, char value) => InsertSpanFormattable(index, value);
18+
19+
/// <summary>
20+
/// Insert the string representation of the signed byte to the builder at the given index.
21+
/// </summary>
22+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
23+
/// <param name="value">String to insert into this builder.</param>
24+
public void Insert(int index, sbyte value) => InsertSpanFormattable(index, value);
25+
26+
/// <summary>
27+
/// Insert the string representation of the byte to the builder at the given index.
28+
/// </summary>
29+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
30+
/// <param name="value">String to insert into this builder.</param>
31+
public void Insert(int index, byte value) => InsertSpanFormattable(index, value);
32+
33+
/// <summary>
34+
/// Insert the string representation of the short to the builder at the given index.
35+
/// </summary>
36+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
37+
/// <param name="value">String to insert into this builder.</param>
38+
public void Insert(int index, short value) => InsertSpanFormattable(index, value);
39+
40+
/// <summary>
41+
/// Insert the string representation of the integer to the builder at the given index.
42+
/// </summary>
43+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
44+
/// <param name="value">String to insert into this builder.</param>
45+
public void Insert(int index, int value) => InsertSpanFormattable(index, value);
46+
47+
/// <summary>
48+
/// Insert the string representation of the long to the builder at the given index.
49+
/// </summary>
50+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
51+
/// <param name="value">String to insert into this builder.</param>
52+
public void Insert(int index, long value) => InsertSpanFormattable(index, value);
53+
54+
/// <summary>
55+
/// Insert the string representation of the float to the builder at the given index.
56+
/// </summary>
57+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
58+
/// <param name="value">String to insert into this builder.</param>
59+
public void Insert(int index, float value) => InsertSpanFormattable(index, value);
60+
61+
/// <summary>
62+
/// Insert the string representation of the double to the builder at the given index.
63+
/// </summary>
64+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
65+
/// <param name="value">String to insert into this builder.</param>
66+
public void Insert(int index, double value) => InsertSpanFormattable(index, value);
67+
68+
/// <summary>
69+
/// Insert the string representation of the decimal to the builder at the given index.
70+
/// </summary>
71+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
72+
/// <param name="value">String to insert into this builder.</param>
73+
public void Insert(int index, decimal value) => InsertSpanFormattable(index, value);
74+
75+
/// <summary>
76+
/// Appends the string representation of the boolean to the builder.
77+
/// </summary>
78+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
79+
/// <param name="value">String to insert into this builder.</param>
80+
public void Insert(int index, ReadOnlySpan<char> value)
81+
{
82+
if (index < 0)
83+
{
84+
throw new ArgumentOutOfRangeException(nameof(index), "The given index can't be negative.");
85+
}
86+
87+
if (index > bufferPosition)
88+
{
89+
throw new ArgumentOutOfRangeException(nameof(index), "The given index can't be bigger than the string itself.");
90+
}
91+
92+
bufferPosition += value.Length;
93+
if (bufferPosition > buffer.Length)
94+
{
95+
Grow(bufferPosition * 2);
96+
}
97+
98+
// Move Slice at beginning index
99+
var oldPosition = bufferPosition - value.Length;
100+
var shift = index + value.Length;
101+
buffer[index..oldPosition].CopyTo(buffer[shift..bufferPosition]);
102+
103+
// Add new word
104+
value.CopyTo(buffer[index..shift]);
105+
}
106+
107+
private void InsertSpanFormattable<T>(int index, T value)
108+
where T : ISpanFormattable
109+
{
110+
if (index < 0)
111+
{
112+
throw new ArgumentOutOfRangeException(nameof(index), "The given index can't be negative.");
113+
}
114+
115+
if (index > bufferPosition)
116+
{
117+
throw new ArgumentOutOfRangeException(nameof(index), "The given index can't be bigger than the string itself.");
118+
}
119+
120+
Span<char> tempBuffer = stackalloc char[24];
121+
if (value.TryFormat(tempBuffer, out var written, default, null))
122+
{
123+
bufferPosition += written;
124+
if (bufferPosition > buffer.Length)
125+
{
126+
Grow(bufferPosition * 2);
127+
}
128+
129+
// Move Slice at beginning index
130+
var oldPosition = bufferPosition - written;
131+
var shift = index + written;
132+
buffer[index..oldPosition].CopyTo(buffer[shift..bufferPosition]);
133+
134+
// Add new word
135+
tempBuffer[..written].CopyTo(buffer[index..shift]);
136+
}
137+
}
138+
}

src/LinkDotNet.StringBuilder/ValueStringBuilder.cs

Lines changed: 4 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ public ValueStringBuilder()
2626
/// <summary>
2727
/// Gets the current length of the represented string.
2828
/// </summary>
29+
/// <value>
30+
/// The current length of the represented string.
31+
/// </value>
2932
public int Length => bufferPosition;
3033

3134
/// <summary>
@@ -34,54 +37,6 @@ public ValueStringBuilder()
3437
/// <param name="index">Index position, which should be retrieved.</param>
3538
public ref char this[int index] => ref buffer[index];
3639

37-
/// <summary>
38-
/// Appends the string representation of the character to the builder.
39-
/// </summary>
40-
/// <param name="value">Integer to add.</param>
41-
public void Append(char value)
42-
{
43-
if (bufferPosition == buffer.Length - 1)
44-
{
45-
Grow();
46-
}
47-
48-
buffer[bufferPosition++] = value;
49-
}
50-
51-
/// <summary>
52-
/// Appends a string to the string builder.
53-
/// </summary>
54-
/// <param name="str">String, which will be added to this builder.</param>
55-
public void Append(ReadOnlySpan<char> str)
56-
{
57-
var newSize = str.Length + bufferPosition;
58-
if (newSize > buffer.Length)
59-
{
60-
Grow(newSize * 2);
61-
}
62-
63-
str.CopyTo(buffer[bufferPosition..]);
64-
bufferPosition += str.Length;
65-
}
66-
67-
/// <summary>
68-
/// Adds the default new line separator.
69-
/// </summary>
70-
public void AppendLine()
71-
{
72-
Append(Environment.NewLine);
73-
}
74-
75-
/// <summary>
76-
/// Does the same as <see cref="Append(char)"/> but adds a newline at the end.
77-
/// </summary>
78-
/// <param name="str">String, which will be added to this builder.</param>
79-
public void AppendLine(ReadOnlySpan<char> str)
80-
{
81-
Append(str);
82-
Append(Environment.NewLine);
83-
}
84-
8540
/// <summary>
8641
/// Creates a <see cref="string"/> instance from that builder.
8742
/// </summary>
@@ -105,7 +60,7 @@ public void AppendLine(ReadOnlySpan<char> str)
10560
/// Clears the internal representation of the string.
10661
/// </summary>
10762
/// <remarks>
108-
/// This will not enforce some allocations or shrinking of the internal buffer.
63+
/// This will not enforce some re-allocation or shrinking of the internal buffer. The size stays the same.
10964
/// </remarks>
11065
public void Clear()
11166
{

tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilderExtensionsTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
13
namespace LinkDotNet.StringBuilder.UnitTests;
24

35
public class ValueStringBuilderExtensionsTests
@@ -23,4 +25,14 @@ public void ShouldConvertFromStringBuilder()
2325

2426
toBuilder.ToString().Should().Be("Hello");
2527
}
28+
29+
[Fact]
30+
public void ShouldThrowWhenStringBuilderNull()
31+
{
32+
System.Text.StringBuilder? sb = null;
33+
34+
Action act = () => sb.ToValueStringBuilder();
35+
36+
act.Should().Throw<ArgumentNullException>();
37+
}
2638
}

0 commit comments

Comments
 (0)