Skip to content

Commit 5c83f8b

Browse files
committed
added options
1 parent 7080bdf commit 5c83f8b

File tree

4 files changed

+89
-5
lines changed

4 files changed

+89
-5
lines changed

src/CountExceedingBehaviour.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace SpanExtensions
2+
{
3+
/// <summary>
4+
/// Defines the behaviour of a split operation when there are more split instances than there may be.
5+
/// </summary>
6+
public enum CountExceedingBehaviour
7+
{
8+
/// <summary>
9+
/// The last element returned will be all the remaining elements appended as one.
10+
/// </summary>
11+
AppendLastElements,
12+
/// <summary>
13+
/// Every split instance more than permitted will not be returned.
14+
/// </summary>
15+
CutLastElements
16+
}
17+
}

src/Enumerators/Split/SpanSplitWithCountEnumerator.cs

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ namespace SpanExtensions.Enumerators
66
/// Supports iteration over a <see cref="ReadOnlySpan{T}"/> by splitting it a a specified delimiter of type <typeparamref name="T"/> with an upper limit of splits performed.
77
/// </summary>
88
/// <typeparam name="T">The type of elements in the enumerated <see cref="ReadOnlySpan{T}"/>.</typeparam>
9-
public ref struct SpanSplitWithCountEnumerator<T> where T : IEquatable<T>
9+
public ref struct SpanSplitWithCountEnumerator<T> where T : IEquatable<T>
1010
{
1111
ReadOnlySpan<T> Span;
1212
readonly T Delimiter;
1313
readonly int Count;
14+
readonly CountExceedingBehaviour CountExceedingBehaviour;
1415
int currentCount;
16+
readonly int CountMinusOne;
1517

1618
/// <summary>
1719
/// Gets the element in the collection at the current position of the enumerator.
@@ -24,13 +26,16 @@ namespace SpanExtensions.Enumerators
2426
/// <param name="source">The <see cref="ReadOnlySpan{T}"/> to be split.</param>
2527
/// <param name="delimiter">An instance of <typeparamref name="T"/> that delimits the various sub-ReadOnlySpans in <paramref name="source"/>.</param>
2628
/// <param name="count">The maximum number of sub-ReadOnlySpans to split into.</param>
27-
public SpanSplitWithCountEnumerator(ReadOnlySpan<T> source, T delimiter, int count)
29+
/// <param name="countExceedingBehaviour">The handling of the instances more than count.</param>
30+
public SpanSplitWithCountEnumerator(ReadOnlySpan<T> source, T delimiter, int count, CountExceedingBehaviour countExceedingBehaviour = CountExceedingBehaviour.CutLastElements)
2831
{
2932
Span = source;
3033
Delimiter = delimiter;
3134
Count = count;
35+
CountExceedingBehaviour = countExceedingBehaviour;
3236
Current = default;
3337
currentCount = 0;
38+
CountMinusOne = Math.Max(Count - 1, 0);
3439
}
3540

3641
/// <summary>
@@ -57,6 +62,26 @@ public bool MoveNext()
5762
return false;
5863
}
5964
int index = span.IndexOf(Delimiter);
65+
switch(CountExceedingBehaviour)
66+
{
67+
case CountExceedingBehaviour.CutLastElements:
68+
break;
69+
case CountExceedingBehaviour.AppendLastElements:
70+
if(currentCount == CountMinusOne)
71+
{
72+
ReadOnlySpan<T> lower = span[..index];
73+
ReadOnlySpan<T> upper = span[(index + 1)..];
74+
Span<T> temp = new T[lower.Length + upper.Length];
75+
lower.CopyTo(temp[..index]);
76+
upper.CopyTo(temp[index..]);
77+
Current = temp;
78+
currentCount++;
79+
return true;
80+
}
81+
break;
82+
default:
83+
throw new InvalidCountExceedingBehaviourException(CountExceedingBehaviour);
84+
}
6085
if(index == -1 || index >= span.Length)
6186
{
6287
Span = ReadOnlySpan<T>.Empty;
@@ -69,4 +94,4 @@ public bool MoveNext()
6994
return true;
7095
}
7196
}
72-
}
97+
}

src/Extensions/ReadOnlySpan/ReadOnlySpanExtensions.String.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-

2-
using System;
1+
using System;
32

43
namespace SpanExtensions
54
{
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
3+
namespace SpanExtensions
4+
{
5+
/// <summary>
6+
/// The Exception that is thrown for an undefined enumeration value of <see cref="CountExceedingBehaviour"/>.
7+
/// </summary>
8+
[Serializable]
9+
public class InvalidCountExceedingBehaviourException : Exception
10+
{
11+
/// <summary>
12+
/// Initializes a new instance of the <see cref="InvalidCountExceedingBehaviourException"/> class with a system-supplied message.
13+
/// </summary>
14+
/// <param name="countExceedingBehaviour"> The invalid <see cref="CountExceedingBehaviour"/>. </param>
15+
public InvalidCountExceedingBehaviourException(CountExceedingBehaviour countExceedingBehaviour) :
16+
base($"CountExceedingBehaviour with ID '{(int) countExceedingBehaviour} is not defined. CountExceedingBehaviour only defines {GetCountExceedingBehaviourNamesListed()}.")
17+
{
18+
19+
}
20+
21+
static string GetCountExceedingBehaviourNamesListed()
22+
{
23+
string[] countExceedingBehaviourNames = Array.Empty<string>();
24+
#if NET5_0_OR_GREATER
25+
countExceedingBehaviourNames = Enum.GetNames<CountExceedingBehaviour>();
26+
#else
27+
countExceedingBehaviourNames = (string[]) Enum.GetNames(typeof(CountExceedingBehaviour));
28+
#endif
29+
switch(countExceedingBehaviourNames.Length)
30+
{
31+
case 0:
32+
return "";
33+
case 1:
34+
return countExceedingBehaviourNames[0];
35+
default:
36+
string first = countExceedingBehaviourNames[0];
37+
string end = string.Join(',', countExceedingBehaviourNames, 1, countExceedingBehaviourNames.Length - 1);
38+
return $"{first} and {end}";
39+
}
40+
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)