Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T

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

## [2.1.0] - 2025-01-14

Expand Down
24 changes: 24 additions & 0 deletions src/LinkDotNet.StringBuilder/ValueStringBuilder.Insert.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Runtime.CompilerServices;
using System.Text;

namespace LinkDotNet.StringBuilder;

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

/// <summary>
/// Insert the string representation of the character to the builder at the given index.
/// </summary>
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
/// <param name="value">Character to insert into this builder.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Insert(int index, char value) => Insert(index, [value]);

/// <summary>
/// Insert the string representation of the rune to the builder at the given index.
/// </summary>
/// <param name="index">Index where <paramref name="value"/> should be inserted.</param>
/// <param name="value">Rune to insert into this builder.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Insert(int index, Rune value)
{
Span<char> valueChars = stackalloc char[2];
int valueCharsWritten = value.EncodeToUtf16(valueChars);
ReadOnlySpan<char> valueCharsReadOnly = valueChars[..valueCharsWritten];

Insert(index, valueCharsReadOnly);
}

/// <summary>
/// Insert the string representation of the char to the builder at the given index.
/// </summary>
Expand Down
35 changes: 14 additions & 21 deletions src/LinkDotNet.StringBuilder/ValueStringBuilder.Replace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,6 @@ public ref partial struct ValueStringBuilder
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void Replace(char oldValue, char newValue) => Replace(oldValue, newValue, 0, Length);

/// <summary>
/// Replaces all instances of one rune with another in this builder.
/// </summary>
/// <param name="oldValue">The rune to replace.</param>
/// <param name="newValue">The rune to replace <paramref name="oldValue"/> with.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Replace(Rune oldValue, Rune newValue)
{
Replace(oldValue, newValue, 0, Length);
}

/// <summary>
/// Replaces all instances of one character with another in this builder.
/// </summary>
Expand All @@ -34,15 +23,8 @@ public void Replace(Rune oldValue, Rune newValue)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly void Replace(char oldValue, char newValue, int startIndex, int count)
{
if (startIndex < 0)
{
throw new ArgumentOutOfRangeException(nameof(startIndex), "Start index can't be smaller than 0.");
}

if (count > bufferPosition)
{
throw new ArgumentOutOfRangeException(nameof(count), $"Count: {count} is bigger than the current size {bufferPosition}.");
}
ArgumentOutOfRangeException.ThrowIfLessThan(startIndex, 0);
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex + count, Length);

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

/// <summary>
/// Replaces all instances of one rune with another in this builder.
/// </summary>
/// <param name="oldValue">The rune to replace.</param>
/// <param name="newValue">The rune to replace <paramref name="oldValue"/> with.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Replace(Rune oldValue, Rune newValue) => Replace(oldValue, newValue, 0, Length);

/// <summary>
/// Replaces all instances of one rune with another in this builder.
/// </summary>
Expand Down Expand Up @@ -99,6 +89,9 @@ public void Replace(scoped ReadOnlySpan<char> oldValue, scoped ReadOnlySpan<char
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Replace(scoped ReadOnlySpan<char> oldValue, scoped ReadOnlySpan<char> newValue, int startIndex, int count)
{
ArgumentOutOfRangeException.ThrowIfLessThan(startIndex, 0);
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex + count, Length);

var length = startIndex + count;
var slice = buffer[startIndex..length];

Expand Down Expand Up @@ -188,7 +181,7 @@ public void ReplaceGeneric<T>(ReadOnlySpan<char> oldValue, T newValue, int start
}
else
{
Replace(oldValue, (ReadOnlySpan<char>)newValue?.ToString(), startIndex, count);
Replace(oldValue, (newValue?.ToString() ?? string.Empty).AsSpan(), startIndex, count);
}
}
}
Loading