From d5476e659e4fbd58970cdd12f9c6002cde54be75 Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Thu, 23 Jan 2025 19:38:16 +0000 Subject: [PATCH 1/3] Add TrimPrefix and TrimSuffix --- .../ValueStringBuilder.Trim.cs | 60 ++++++++++++++----- .../ValueStringBuilder.cs | 19 ++---- .../ValueStringBuilder.Trim.Tests.cs | 22 +++++++ 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/LinkDotNet.StringBuilder/ValueStringBuilder.Trim.cs b/src/LinkDotNet.StringBuilder/ValueStringBuilder.Trim.cs index c9a71ee..6da1fba 100644 --- a/src/LinkDotNet.StringBuilder/ValueStringBuilder.Trim.cs +++ b/src/LinkDotNet.StringBuilder/ValueStringBuilder.Trim.cs @@ -5,7 +5,7 @@ namespace LinkDotNet.StringBuilder; public ref partial struct ValueStringBuilder { /// - /// Removes a set of whitespace characters from the beginning and ending of this string. + /// Removes all whitespace characters from the start and end of this builder. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Trim() @@ -33,22 +33,22 @@ public void Trim() } /// - /// Removes the specified character from the beginning and end of this string. + /// Removes all occurrences of the specified character from the start and end of this builder. /// - /// The character to remove. + /// The character to remove. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Trim(char c) + public void Trim(char value) { // Remove character from the beginning var start = 0; - while (start < bufferPosition && buffer[start] == c) + while (start < bufferPosition && buffer[start] == value) { start++; } // Remove character from the end var end = bufferPosition - 1; - while (end >= start && buffer[end] == c) + while (end >= start && buffer[end] == value) { end--; } @@ -62,7 +62,7 @@ public void Trim(char c) } /// - /// Removes a set of whitespace characters from the beginning of this string. + /// Removes all whitespace characters from the start of this builder. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TrimStart() @@ -82,14 +82,14 @@ public void TrimStart() } /// - /// Removes the specified character from the beginning of this string. + /// Removes all occurrences of the specified character from the start of this builder. /// - /// The character to remove. + /// The character to remove. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void TrimStart(char c) + public void TrimStart(char value) { var start = 0; - while (start < bufferPosition && buffer[start] == c) + while (start < bufferPosition && buffer[start] == value) { start++; } @@ -103,7 +103,7 @@ public void TrimStart(char c) } /// - /// Removes a set of whitespace characters from the ending of this string. + /// Removes all whitespace characters from the end of this builder. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TrimEnd() @@ -118,18 +118,46 @@ public void TrimEnd() } /// - /// Removes the specified character from the end of this string. + /// Removes all occurrences of the specified character from the end of this builder. /// - /// The character to remove. + /// The character to remove. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void TrimEnd(char c) + public void TrimEnd(char value) { var end = bufferPosition - 1; - while (end >= 0 && buffer[end] == c) + while (end >= 0 && buffer[end] == value) { end--; } bufferPosition = end + 1; } + + /// + /// Removes the specified sequence of characters from the start of this builder. + /// + /// The sequence of characters to remove. + /// The way to compare the sequences of characters. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void TrimPrefix(ReadOnlySpan value, StringComparison comparisonType = StringComparison.Ordinal) + { + if (AsSpan().StartsWith(value, comparisonType)) + { + Remove(0, value.Length); + } + } + + /// + /// Removes the specified sequence of characters from the end of this builder. + /// + /// The sequence of characters to remove. + /// The way to compare the sequences of characters. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void TrimSuffix(ReadOnlySpan value, StringComparison comparisonType = StringComparison.Ordinal) + { + if (AsSpan().EndsWith(value, comparisonType)) + { + Remove(Length - value.Length, value.Length); + } + } } \ No newline at end of file diff --git a/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs b/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs index b190a44..a02a663 100644 --- a/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs +++ b/src/LinkDotNet.StringBuilder/ValueStringBuilder.cs @@ -199,26 +199,15 @@ public void EnsureCapacity(int newCapacity) [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Remove(int startIndex, int length) { + ArgumentOutOfRangeException.ThrowIfLessThan(length, 0); + ArgumentOutOfRangeException.ThrowIfLessThan(startIndex, 0); + ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex + length, Length); + if (length == 0) { return; } - if (length < 0) - { - throw new ArgumentOutOfRangeException(nameof(length), "The given length can't be negative."); - } - - if (startIndex < 0) - { - throw new ArgumentOutOfRangeException(nameof(startIndex), "The given start index can't be negative."); - } - - if (length > Length - startIndex) - { - throw new ArgumentOutOfRangeException(nameof(length), $"The given Span ({startIndex}..{length})length is outside the the represented string."); - } - var beginIndex = startIndex + length; buffer[beginIndex..bufferPosition].CopyTo(buffer[startIndex..]); bufferPosition -= length; diff --git a/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs b/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs index f616681..0491dfe 100644 --- a/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs +++ b/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs @@ -79,4 +79,26 @@ public void GivenString_WhenTrimCharacter_ThenShouldRemoveCharacter() valueStringBuilder.ToString().ShouldBe("ee"); } + + [Fact] + public void GivenString_WhenTrimPrefix_ThenShouldRemoveSpan() + { + using var valueStringBuilder = new ValueStringBuilder(); + valueStringBuilder.Append("Hello world"); + + valueStringBuilder.TrimPrefix("hell", System.StringComparison.InvariantCultureIgnoreCase); + + valueStringBuilder.ToString().ShouldBe("o world"); + } + + [Fact] + public void GivenString_WhenTrimSuffix_ThenShouldRemoveSpan() + { + using var valueStringBuilder = new ValueStringBuilder(); + valueStringBuilder.Append("Hello world"); + + valueStringBuilder.TrimPrefix("RlD", System.StringComparison.InvariantCultureIgnoreCase); + + valueStringBuilder.ToString().ShouldBe("Hello wo"); + } } \ No newline at end of file From e67051ed8501ae88d265baf63f3f0e2bb251a7bf Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Thu, 23 Jan 2025 19:49:06 +0000 Subject: [PATCH 2/3] Fix unit tests --- .../ValueStringBuilder.Trim.Tests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs b/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs index 0491dfe..8e52ddd 100644 --- a/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs +++ b/tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Trim.Tests.cs @@ -1,3 +1,5 @@ +using System; + namespace LinkDotNet.StringBuilder.UnitTests; public class ValueStringBuilderTrimTests @@ -86,7 +88,7 @@ public void GivenString_WhenTrimPrefix_ThenShouldRemoveSpan() using var valueStringBuilder = new ValueStringBuilder(); valueStringBuilder.Append("Hello world"); - valueStringBuilder.TrimPrefix("hell", System.StringComparison.InvariantCultureIgnoreCase); + valueStringBuilder.TrimPrefix("hell", StringComparison.InvariantCultureIgnoreCase); valueStringBuilder.ToString().ShouldBe("o world"); } @@ -97,7 +99,7 @@ public void GivenString_WhenTrimSuffix_ThenShouldRemoveSpan() using var valueStringBuilder = new ValueStringBuilder(); valueStringBuilder.Append("Hello world"); - valueStringBuilder.TrimPrefix("RlD", System.StringComparison.InvariantCultureIgnoreCase); + valueStringBuilder.TrimSuffix("RlD", StringComparison.InvariantCultureIgnoreCase); valueStringBuilder.ToString().ShouldBe("Hello wo"); } From 45a85ef3a39bbcc2583e0d4de6e9b46fd96b9771 Mon Sep 17 00:00:00 2001 From: Joyless <65855333+Joy-less@users.noreply.github.com> Date: Thu, 23 Jan 2025 20:50:04 +0000 Subject: [PATCH 3/3] Update CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d55c727..3017007 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T ## [Unreleased] +### Added + +- Added `TrimPrefix(ReadOnlySpan, StringComparison)` (by yours truly (@Joy-less) in #226) +- Added `TrimSuffix(ReadOnlySpan, StringComparison)` (also by yours truly (@Joy-less) in #226) + ## [2.1.0] - 2025-01-14 ### Added