Skip to content

Commit 909f2fd

Browse files
committed
Added AppendJoin methods
1 parent 5d96086 commit 909f2fd

File tree

6 files changed

+238
-64
lines changed

6 files changed

+238
-64
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ All notable changes to **ValueStringBuilder** will be documented in this file. T
66

77
## [Unreleased]
88

9+
### Added
10+
- Added `AppendJoin` methods.
11+
912
## [0.9.3] - 2022-04-09
1013

1114
### Added
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
namespace LinkDotNet.StringBuilder;
2+
3+
public ref partial struct ValueStringBuilder
4+
{
5+
/// <summary>
6+
/// Concatenates and appends all values with the given separator between each entry at the end of the string.
7+
/// </summary>
8+
/// <param name="separator">String used as separator between the entries.</param>
9+
/// <param name="values">Array of strings, which will be concatenated.</param>
10+
public void AppendJoin(ReadOnlySpan<char> separator, IEnumerable<string?> values)
11+
=> AppendJoinInternalString(separator, values);
12+
13+
/// <summary>
14+
/// Concatenates and appends all values with the given separator between each entry at the end of the string.
15+
/// </summary>
16+
/// <param name="separator">Character used as separator between the entries.</param>
17+
/// <param name="values">Array of strings, which will be concatenated.</param>
18+
public void AppendJoin(char separator, IEnumerable<string?> values)
19+
=> AppendJoinInternalChar(separator, values);
20+
21+
/// <summary>
22+
/// Concatenates and appends all values with the given separator between each entry at the end of the string.
23+
/// </summary>
24+
/// <param name="separator">String used as separator between the entries.</param>
25+
/// <param name="values">Array of strings, which will be concatenated.</param>
26+
/// <typeparam name="T">Type of the given array.</typeparam>
27+
public void AppendJoin<T>(ReadOnlySpan<char> separator, IEnumerable<T> values)
28+
=> AppendJoinInternalString(separator, values);
29+
30+
/// <summary>
31+
/// Concatenates and appends all values with the given separator between each entry at the end of the string.
32+
/// </summary>
33+
/// <param name="separator">Character used as separator between the entries.</param>
34+
/// <param name="values">Array of strings, which will be concatenated.</param>
35+
/// <typeparam name="T">Type of the given array.</typeparam>
36+
public void AppendJoin<T>(char separator, IEnumerable<T> values)
37+
=> AppendJoinInternalChar(separator, values);
38+
39+
private void AppendJoinInternalString<T2>(ReadOnlySpan<char> separator, IEnumerable<T2> values)
40+
{
41+
ArgumentNullException.ThrowIfNull(values);
42+
43+
using var enumerator = values.GetEnumerator();
44+
45+
if (!enumerator.MoveNext())
46+
{
47+
return;
48+
}
49+
50+
var current = enumerator.Current;
51+
if (current != null)
52+
{
53+
AppendInternal(current);
54+
}
55+
56+
while (enumerator.MoveNext())
57+
{
58+
Append(separator);
59+
current = enumerator.Current;
60+
if (current != null)
61+
{
62+
AppendInternal(current);
63+
}
64+
}
65+
}
66+
67+
private void AppendJoinInternalChar<T2>(char separator, IEnumerable<T2> values)
68+
{
69+
ArgumentNullException.ThrowIfNull(values);
70+
71+
using var enumerator = values.GetEnumerator();
72+
73+
if (!enumerator.MoveNext())
74+
{
75+
return;
76+
}
77+
78+
var current = enumerator.Current;
79+
if (current != null)
80+
{
81+
AppendInternal(current);
82+
}
83+
84+
while (enumerator.MoveNext())
85+
{
86+
AppendInternal(separator);
87+
current = enumerator.Current;
88+
if (current != null)
89+
{
90+
AppendInternal(current);
91+
}
92+
}
93+
}
94+
95+
private void AppendInternal<T>(T value)
96+
{
97+
if (value is ISpanFormattable spanFormattable)
98+
{
99+
AppendSpanFormattable(spanFormattable);
100+
}
101+
else
102+
{
103+
Append(value?.ToString());
104+
}
105+
}
106+
}

tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.AppendSpanFormattable.Tests.cs renamed to tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Append.Tests.cs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,72 @@
1+
using System;
2+
13
namespace LinkDotNet.StringBuilder.UnitTests;
24

3-
public class ValueStringBuilderAppendFormattableTests
5+
public class ValueStringBuilderAppendTests
46
{
7+
[Fact]
8+
public void ShouldAddString()
9+
{
10+
var stringBuilder = new ValueStringBuilder();
11+
12+
stringBuilder.Append("That is a string");
13+
14+
stringBuilder.ToString().Should().Be("That is a string");
15+
}
16+
17+
[Fact]
18+
public void ShouldAddMultipleStrings()
19+
{
20+
var stringBuilder = new ValueStringBuilder();
21+
22+
stringBuilder.Append("This");
23+
stringBuilder.Append("is");
24+
stringBuilder.Append("a");
25+
stringBuilder.Append("test");
26+
27+
stringBuilder.ToString().Should().Be("Thisisatest");
28+
}
29+
30+
[Fact]
31+
public void ShouldAddLargeStrings()
32+
{
33+
var stringBuilder = new ValueStringBuilder();
34+
35+
stringBuilder.Append(new string('c', 99));
36+
37+
stringBuilder.ToString().Should().MatchRegex("[c]{99}");
38+
}
39+
40+
[Fact]
41+
public void ShouldAppendLine()
42+
{
43+
var stringBuilder = new ValueStringBuilder();
44+
45+
stringBuilder.AppendLine("Hello");
46+
47+
stringBuilder.ToString().Should().Contain("Hello").And.Contain(Environment.NewLine);
48+
}
49+
50+
[Fact]
51+
public void ShouldOnlyAddNewline()
52+
{
53+
var stringBuilder = new ValueStringBuilder();
54+
55+
stringBuilder.AppendLine();
56+
57+
stringBuilder.ToString().Should().Be(Environment.NewLine);
58+
}
59+
60+
[Fact]
61+
public void ShouldGetIndexIfGiven()
62+
{
63+
var stringBuilder = new ValueStringBuilder();
64+
65+
stringBuilder.Append("Hello");
66+
67+
stringBuilder[2].Should().Be('l');
68+
}
69+
570
[Fact]
671
public void ShouldAppendFloat()
772
{
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace LinkDotNet.StringBuilder.UnitTests;
5+
6+
public class ValueStringBuilderAppendJoinTests
7+
{
8+
[Theory]
9+
[MemberData(nameof(StringSeparatorTestData))]
10+
public void ShouldAppendWithStringSeparator(string separator, IEnumerable<string?> values, string expected)
11+
{
12+
var stringBuilder = new ValueStringBuilder();
13+
14+
stringBuilder.AppendJoin(separator, values);
15+
16+
stringBuilder.ToString().Should().Be(expected);
17+
}
18+
19+
[Theory]
20+
[MemberData(nameof(CharSeparatorTestData))]
21+
public void ShouldAppendWithCharSeparator(char separator, IEnumerable<string?> values, string expected)
22+
{
23+
var stringBuilder = new ValueStringBuilder();
24+
25+
stringBuilder.AppendJoin(separator, values);
26+
27+
stringBuilder.ToString().Should().Be(expected);
28+
}
29+
30+
[Fact]
31+
public void ShouldAddDataWithStringSeparator()
32+
{
33+
var stringBuilder = new ValueStringBuilder();
34+
35+
stringBuilder.AppendJoin(",", new object[] { 1, new DateTime(1900, 1, 1) });
36+
37+
stringBuilder.ToString().Should().Be("1,01/01/1900 00:00:00");
38+
}
39+
40+
[Fact]
41+
public void ShouldAddDataWithCharSeparator()
42+
{
43+
var stringBuilder = new ValueStringBuilder();
44+
45+
stringBuilder.AppendJoin(',', new object[] { 1, new DateTime(1900, 1, 1) });
46+
47+
stringBuilder.ToString().Should().Be("1,01/01/1900 00:00:00");
48+
}
49+
50+
private static IEnumerable<object[]> StringSeparatorTestData()
51+
{
52+
yield return new object[] { ",", new[] { "Hello", "World" }, "Hello,World" };
53+
yield return new object[] { ",", new[] { "Hello" }, "Hello" };
54+
yield return new object[] { ",", Array.Empty<string>(), string.Empty };
55+
}
56+
57+
private static IEnumerable<object[]> CharSeparatorTestData()
58+
{
59+
yield return new object[] { ',', new[] { "Hello", "World" }, "Hello,World" };
60+
yield return new object[] { ',', new[] { "Hello" }, "Hello" };
61+
yield return new object[] { ',', Array.Empty<string>(), string.Empty };
62+
}
63+
}

tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilderInsertTests.cs renamed to tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilder.Insert.Tests.cs

File renamed without changes.

tests/LinkDotNet.StringBuilder.UnitTests/ValueStringBuilderTests.cs

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,69 +4,6 @@ namespace LinkDotNet.StringBuilder.UnitTests;
44

55
public class ValueStringBuilderTests
66
{
7-
[Fact]
8-
public void ShouldAddString()
9-
{
10-
var stringBuilder = new ValueStringBuilder();
11-
12-
stringBuilder.Append("That is a string");
13-
14-
stringBuilder.ToString().Should().Be("That is a string");
15-
}
16-
17-
[Fact]
18-
public void ShouldAddMultipleStrings()
19-
{
20-
var stringBuilder = new ValueStringBuilder();
21-
22-
stringBuilder.Append("This");
23-
stringBuilder.Append("is");
24-
stringBuilder.Append("a");
25-
stringBuilder.Append("test");
26-
27-
stringBuilder.ToString().Should().Be("Thisisatest");
28-
}
29-
30-
[Fact]
31-
public void ShouldAddLargeStrings()
32-
{
33-
var stringBuilder = new ValueStringBuilder();
34-
35-
stringBuilder.Append(new string('c', 99));
36-
37-
stringBuilder.ToString().Should().MatchRegex("[c]{99}");
38-
}
39-
40-
[Fact]
41-
public void ShouldAppendLine()
42-
{
43-
var stringBuilder = new ValueStringBuilder();
44-
45-
stringBuilder.AppendLine("Hello");
46-
47-
stringBuilder.ToString().Should().Contain("Hello").And.Contain(Environment.NewLine);
48-
}
49-
50-
[Fact]
51-
public void ShouldOnlyAddNewline()
52-
{
53-
var stringBuilder = new ValueStringBuilder();
54-
55-
stringBuilder.AppendLine();
56-
57-
stringBuilder.ToString().Should().Be(Environment.NewLine);
58-
}
59-
60-
[Fact]
61-
public void ShouldGetIndexIfGiven()
62-
{
63-
var stringBuilder = new ValueStringBuilder();
64-
65-
stringBuilder.Append("Hello");
66-
67-
stringBuilder[2].Should().Be('l');
68-
}
69-
707
[Fact]
718
public void ShouldThrowIndexOutOfRangeWhenStringShorterThanIndex()
729
{

0 commit comments

Comments
 (0)