Skip to content

Commit 1dc4866

Browse files
committed
Removed debugging and add NaiveSearch instead of BoyerMoore
1 parent 1943452 commit 1dc4866

File tree

5 files changed

+74
-95
lines changed

5 files changed

+74
-95
lines changed

logo.png

-65 Bytes
Loading

src/LinkDotNet.StringBuilder/BoyerMooreSearch.cs

Lines changed: 0 additions & 87 deletions
This file was deleted.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
namespace LinkDotNet.StringBuilder;
2+
3+
internal static class NaiveSearch
4+
{
5+
/// <summary>
6+
/// Finds all occurence of <paramref name="word"/> in <paramref name="text"/>.
7+
/// </summary>
8+
/// <param name="text">The text to look for.</param>
9+
/// <param name="word">The word which should be found in <paramref name="word"/>.</param>
10+
/// <returns>Array of indexes where <paramref name="word"/> was found.</returns>
11+
public static ReadOnlySpan<int> FindAll(ReadOnlySpan<char> text, ReadOnlySpan<char> word)
12+
{
13+
if (text.IsEmpty || word.IsEmpty)
14+
{
15+
return Array.Empty<int>();
16+
}
17+
18+
if (text.Length < word.Length)
19+
{
20+
return Array.Empty<int>();
21+
}
22+
23+
var hits = new TypedSpanList<int>();
24+
25+
for (var i = 0; i < text.Length; i++)
26+
{
27+
for (var j = 0; j < word.Length; j++)
28+
{
29+
if (text[i + j] != word[j])
30+
{
31+
break;
32+
}
33+
34+
if (j == word.Length - 1)
35+
{
36+
hits.Add(i);
37+
}
38+
}
39+
}
40+
41+
return hits.AsSpan;
42+
}
43+
}

src/LinkDotNet.StringBuilder/ValueStringBuilder.Replace.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ public void Replace(char oldValue, char newValue, int startIndex, int count)
4646
/// If <paramref name="newValue"/> is <c>empty</c>, instances of <paramref name="oldValue"/>
4747
/// are removed from this builder.
4848
/// </remarks>
49-
public void Replace(ReadOnlySpan<char> oldValue, ReadOnlySpan<char> newValue) => Replace(oldValue, newValue, 0, Length);
49+
public void Replace(ReadOnlySpan<char> oldValue, ReadOnlySpan<char> newValue)
50+
=> Replace(oldValue, newValue, 0, Length);
5051

5152
/// <summary>
5253
/// Replaces all instances of one string with another in this builder.
@@ -64,8 +65,12 @@ public void Replace(ReadOnlySpan<char> oldValue, ReadOnlySpan<char> newValue, in
6465
var length = startIndex + count;
6566
var slice = buffer[startIndex..length];
6667

67-
// We might want to check if for very small strings we go with a naive approach
68-
var hits = BoyerMooreSearch.FindAll(slice, oldValue);
68+
// We might want to check whether or not we want to introduce different
69+
// string search algorithms for longer strings.
70+
// I had checked initially with Boyer-Moore but it didn't make that much sense as we
71+
// don't expect very long strings and then the performance is literally the same. So I went with the easier solution.
72+
var hits = NaiveSearch.FindAll(slice, oldValue);
73+
6974
if (hits.IsEmpty)
7075
{
7176
return;
@@ -75,13 +80,9 @@ public void Replace(ReadOnlySpan<char> oldValue, ReadOnlySpan<char> newValue, in
7580

7681
for (var i = 0; i < hits.Length; i++)
7782
{
78-
var index = startIndex + hits[0] + (delta * i);
83+
var index = startIndex + hits[i] + (delta * i);
7984
Remove(index, oldValue.Length);
80-
var debug = ToString();
81-
Console.WriteLine(debug);
8285
Insert(index, newValue);
83-
debug = ToString();
84-
Console.WriteLine(debug);
8586
}
8687
}
8788
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,26 @@ public void ShouldReplaceAllText()
3434

3535
builder.ToString().Should().Be("Hallöchen World. How are you doing. Hallöchen world examples are always fun.");
3636
}
37+
38+
[Fact]
39+
public void ShouldNotAlterIfNotFound()
40+
{
41+
var builder = new ValueStringBuilder();
42+
builder.Append("Hello");
43+
44+
builder.Replace("Test", "Not");
45+
46+
builder.ToString().Should().Be("Hello");
47+
}
48+
49+
[Fact]
50+
public void ShouldReplaceInSpan()
51+
{
52+
var builder = new ValueStringBuilder();
53+
builder.Append("Hello World. How are you doing. Hello world examples are always fun.");
54+
55+
builder.Replace("Hello", "Hallöchen", 0, 10);
56+
57+
builder.ToString().Should().Be("Hallöchen World. How are you doing. Hello world examples are always fun.");
58+
}
3759
}

0 commit comments

Comments
 (0)