Skip to content

Commit b68394a

Browse files
authored
Merge pull request #225 from Joy-less/runes-replace-insert
Add insert & replace methods for runes
2 parents 979deb9 + 33bf847 commit b68394a

File tree

4 files changed

+50
-29
lines changed

4 files changed

+50
-29
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T
1010

1111
- Added `TrimPrefix(ReadOnlySpan<char>, StringComparison)` (by yours truly (@Joy-less) in #226)
1212
- Added `TrimSuffix(ReadOnlySpan<char>, StringComparison)` (also by yours truly (@Joy-less) in #226)
13+
- Added `Insert(int, char)` overload (by yours truly (@Joy-less) in #225)
14+
- Added `Insert(int, Rune)` overload (again by yours truly (@Joy-less) in #225)
15+
- Added `Replace(Rune, Rune)` overload (see yours truly (@Joy-less) in #225)
16+
- Improved `Replace(scoped ReadOnlySpan<char>, scoped ReadOnlySpan<char>, int, int)` fallback (achieved by yours truly (@Joy-less) in #225)
1317

1418
## [2.1.0] - 2025-01-14
1519

src/LinkDotNet.StringBuilder/ValueStringBuilder.Append.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,10 @@ public void Append(char value)
126126
public void Append(Rune value)
127127
{
128128
Span<char> valueChars = stackalloc char[2];
129-
int valueCharsWritten = value.EncodeToUtf16(valueChars);
130-
ReadOnlySpan<char> valueCharsReadOnly = valueChars[..valueCharsWritten];
129+
var valueCharsWritten = value.EncodeToUtf16(valueChars);
130+
ReadOnlySpan<char> valueCharsSlice = valueChars[..valueCharsWritten];
131131

132-
Append(valueCharsReadOnly);
132+
Append(valueCharsSlice);
133133
}
134134

135135
/// <summary>

src/LinkDotNet.StringBuilder/ValueStringBuilder.Insert.cs

+24
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Runtime.CompilerServices;
2+
using System.Text;
23

34
namespace LinkDotNet.StringBuilder;
45

@@ -12,6 +13,29 @@ public ref partial struct ValueStringBuilder
1213
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1314
public void Insert(int index, bool value) => Insert(index, value.ToString());
1415

16+
/// <summary>
17+
/// Insert the string representation of the character to the builder at the given index.
18+
/// </summary>
19+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
20+
/// <param name="value">Character to insert into this builder.</param>
21+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
22+
public void Insert(int index, char value) => Insert(index, [value]);
23+
24+
/// <summary>
25+
/// Insert the string representation of the rune to the builder at the given index.
26+
/// </summary>
27+
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
28+
/// <param name="value">Rune to insert into this builder.</param>
29+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
30+
public void Insert(int index, Rune value)
31+
{
32+
Span<char> valueChars = stackalloc char[2];
33+
var valueCharsWritten = value.EncodeToUtf16(valueChars);
34+
ReadOnlySpan<char> valueCharsSlice = valueChars[..valueCharsWritten];
35+
36+
Insert(index, valueCharsSlice);
37+
}
38+
1539
/// <summary>
1640
/// Insert the string representation of the char to the builder at the given index.
1741
/// </summary>

src/LinkDotNet.StringBuilder/ValueStringBuilder.Replace.cs

+19-26
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,6 @@ public ref partial struct ValueStringBuilder
1313
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1414
public readonly void Replace(char oldValue, char newValue) => Replace(oldValue, newValue, 0, Length);
1515

16-
/// <summary>
17-
/// Replaces all instances of one rune with another in this builder.
18-
/// </summary>
19-
/// <param name="oldValue">The rune to replace.</param>
20-
/// <param name="newValue">The rune to replace <paramref name="oldValue"/> with.</param>
21-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
22-
public void Replace(Rune oldValue, Rune newValue)
23-
{
24-
Replace(oldValue, newValue, 0, Length);
25-
}
26-
2716
/// <summary>
2817
/// Replaces all instances of one character with another in this builder.
2918
/// </summary>
@@ -34,15 +23,8 @@ public void Replace(Rune oldValue, Rune newValue)
3423
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3524
public readonly void Replace(char oldValue, char newValue, int startIndex, int count)
3625
{
37-
if (startIndex < 0)
38-
{
39-
throw new ArgumentOutOfRangeException(nameof(startIndex), "Start index can't be smaller than 0.");
40-
}
41-
42-
if (count > bufferPosition)
43-
{
44-
throw new ArgumentOutOfRangeException(nameof(count), $"Count: {count} is bigger than the current size {bufferPosition}.");
45-
}
26+
ArgumentOutOfRangeException.ThrowIfLessThan(startIndex, 0);
27+
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex + count, Length);
4628

4729
for (var i = startIndex; i < startIndex + count; i++)
4830
{
@@ -53,6 +35,14 @@ public readonly void Replace(char oldValue, char newValue, int startIndex, int c
5335
}
5436
}
5537

38+
/// <summary>
39+
/// Replaces all instances of one rune with another in this builder.
40+
/// </summary>
41+
/// <param name="oldValue">The rune to replace.</param>
42+
/// <param name="newValue">The rune to replace <paramref name="oldValue"/> with.</param>
43+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
44+
public void Replace(Rune oldValue, Rune newValue) => Replace(oldValue, newValue, 0, Length);
45+
5646
/// <summary>
5747
/// Replaces all instances of one rune with another in this builder.
5848
/// </summary>
@@ -64,14 +54,14 @@ public readonly void Replace(char oldValue, char newValue, int startIndex, int c
6454
public void Replace(Rune oldValue, Rune newValue, int startIndex, int count)
6555
{
6656
Span<char> oldValueChars = stackalloc char[2];
67-
int oldValueCharsWritten = oldValue.EncodeToUtf16(oldValueChars);
68-
ReadOnlySpan<char> oldValueCharsReadOnly = oldValueChars[..oldValueCharsWritten];
57+
var oldValueCharsWritten = oldValue.EncodeToUtf16(oldValueChars);
58+
ReadOnlySpan<char> oldValueCharsSlice = oldValueChars[..oldValueCharsWritten];
6959

7060
Span<char> newValueChars = stackalloc char[2];
71-
int newValueCharsWritten = newValue.EncodeToUtf16(newValueChars);
72-
ReadOnlySpan<char> newValueCharsReadOnly = newValueChars[..newValueCharsWritten];
61+
var newValueCharsWritten = newValue.EncodeToUtf16(newValueChars);
62+
ReadOnlySpan<char> newValueCharsSlice = newValueChars[..newValueCharsWritten];
7363

74-
Replace(oldValueCharsReadOnly, newValueCharsReadOnly, startIndex, count);
64+
Replace(oldValueCharsSlice, newValueCharsSlice, startIndex, count);
7565
}
7666

7767
/// <summary>
@@ -99,6 +89,9 @@ public void Replace(scoped ReadOnlySpan<char> oldValue, scoped ReadOnlySpan<char
9989
[MethodImpl(MethodImplOptions.AggressiveInlining)]
10090
public void Replace(scoped ReadOnlySpan<char> oldValue, scoped ReadOnlySpan<char> newValue, int startIndex, int count)
10191
{
92+
ArgumentOutOfRangeException.ThrowIfLessThan(startIndex, 0);
93+
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex + count, Length);
94+
10295
var length = startIndex + count;
10396
var slice = buffer[startIndex..length];
10497

@@ -188,7 +181,7 @@ public void ReplaceGeneric<T>(ReadOnlySpan<char> oldValue, T newValue, int start
188181
}
189182
else
190183
{
191-
Replace(oldValue, (ReadOnlySpan<char>)newValue?.ToString(), startIndex, count);
184+
Replace(oldValue, (newValue?.ToString() ?? string.Empty).AsSpan(), startIndex, count);
192185
}
193186
}
194187
}

0 commit comments

Comments
 (0)