Skip to content

Commit ea1e61d

Browse files
Guiorgydragon7307
andauthored
fixed enumeration dropped last span if empty (#10)
Co-authored-by: dragon <[email protected]>
1 parent f46c5ac commit ea1e61d

12 files changed

+144
-37
lines changed

src/Enumerators/Split/SpanSplitEnumerator.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ namespace SpanExtensions.Enumerators
1010
{
1111
ReadOnlySpan<T> Span;
1212
readonly T Delimiter;
13+
bool enumerationDone;
1314

1415
/// <summary>
1516
/// Gets the element in the collection at the current position of the enumerator.
@@ -26,6 +27,7 @@ public SpanSplitEnumerator(ReadOnlySpan<T> source, T delimiter)
2627
Span = source;
2728
Delimiter = delimiter;
2829
Current = default;
30+
enumerationDone = false;
2931
}
3032

3133
/// <summary>
@@ -42,16 +44,17 @@ public readonly SpanSplitEnumerator<T> GetEnumerator()
4244
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
4345
public bool MoveNext()
4446
{
45-
ReadOnlySpan<T> span = Span;
46-
if(span.IsEmpty)
47+
if(enumerationDone)
4748
{
4849
return false;
4950
}
51+
52+
ReadOnlySpan<T> span = Span;
5053
int index = span.IndexOf(Delimiter);
5154

5255
if(index == -1 || index >= span.Length)
5356
{
54-
Span = ReadOnlySpan<T>.Empty;
57+
enumerationDone = true;
5558
Current = span;
5659
return true;
5760
}

src/Enumerators/Split/SpanSplitStringSplitOptionsEnumerator.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public ref struct SpanSplitStringSplitOptionsEnumerator
1010
ReadOnlySpan<char> Span;
1111
readonly char Delimiter;
1212
readonly StringSplitOptions Options;
13+
bool enumerationDone;
1314

1415
/// <summary>
1516
/// Gets the element in the collection at the current position of the enumerator.
@@ -28,6 +29,7 @@ public SpanSplitStringSplitOptionsEnumerator(ReadOnlySpan<char> source, char del
2829
Delimiter = delimiter;
2930
Options = options;
3031
Current = default;
32+
enumerationDone = false;
3133
}
3234

3335
/// <summary>
@@ -44,16 +46,17 @@ public readonly SpanSplitStringSplitOptionsEnumerator GetEnumerator()
4446
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
4547
public bool MoveNext()
4648
{
47-
ReadOnlySpan<char> span = Span;
48-
if(span.IsEmpty)
49+
if(enumerationDone)
4950
{
5051
return false;
5152
}
53+
54+
ReadOnlySpan<char> span = Span;
5255
int index = span.IndexOf(Delimiter);
5356

5457
if(index == -1 || index >= span.Length)
5558
{
56-
Span = ReadOnlySpan<char>.Empty;
59+
enumerationDone = true;
5760
Current = span;
5861
return true;
5962
}
@@ -69,8 +72,20 @@ public bool MoveNext()
6972
if(Current.IsEmpty)
7073
{
7174
Span = span[(index + 1)..];
75+
if(Span.IsEmpty)
76+
{
77+
enumerationDone = true;
78+
return false;
79+
}
7280
return MoveNext();
7381
}
82+
83+
Span = span[(index + 1)..];
84+
if(Span.IsEmpty)
85+
{
86+
enumerationDone = true;
87+
}
88+
return true;
7489
}
7590
Span = span[(index + 1)..];
7691
return true;

src/Enumerators/Split/SpanSplitStringSplitOptionsWithCountEnumerator.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public ref struct SpanSplitStringSplitOptionsWithCountEnumerator
1313
readonly int Count;
1414
readonly CountExceedingBehaviour CountExceedingBehaviour;
1515
int currentCount;
16+
bool enumerationDone;
1617
readonly int CountMinusOne;
1718

1819
/// <summary>
@@ -37,6 +38,7 @@ public SpanSplitStringSplitOptionsWithCountEnumerator(ReadOnlySpan<char> source,
3738
Options = options;
3839
Current = default;
3940
currentCount = 0;
41+
enumerationDone = false;
4042
CountMinusOne = Math.Max(Count - 1, 0);
4143
}
4244

@@ -54,11 +56,12 @@ public readonly SpanSplitStringSplitOptionsWithCountEnumerator GetEnumerator()
5456
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
5557
public bool MoveNext()
5658
{
57-
ReadOnlySpan<char> span = Span;
58-
if(span.IsEmpty)
59+
if(enumerationDone)
5960
{
6061
return false;
6162
}
63+
64+
ReadOnlySpan<char> span = Span;
6265
if(currentCount == Count)
6366
{
6467
return false;
@@ -87,7 +90,7 @@ public bool MoveNext()
8790
}
8891
if(index == -1 || index >= span.Length)
8992
{
90-
Span = ReadOnlySpan<char>.Empty;
93+
enumerationDone = true;
9194
Current = span;
9295
return true;
9396
}
@@ -105,8 +108,20 @@ public bool MoveNext()
105108
if(Current.IsEmpty)
106109
{
107110
Span = span[(index + 1)..];
111+
if(Span.IsEmpty)
112+
{
113+
enumerationDone = true;
114+
return false;
115+
}
108116
return MoveNext();
109117
}
118+
119+
Span = span[(index + 1)..];
120+
if(Span.IsEmpty)
121+
{
122+
enumerationDone = true;
123+
}
124+
return true;
110125
}
111126
Span = span[(index + 1)..];
112127
return true;

src/Enumerators/Split/SpanSplitWithCountEnumerator.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace SpanExtensions.Enumerators
1313
readonly int Count;
1414
readonly CountExceedingBehaviour CountExceedingBehaviour;
1515
int currentCount;
16+
bool enumerationDone;
1617
readonly int CountMinusOne;
1718

1819
/// <summary>
@@ -35,6 +36,7 @@ public SpanSplitWithCountEnumerator(ReadOnlySpan<T> source, T delimiter, int cou
3536
CountExceedingBehaviour = countExceedingBehaviour;
3637
Current = default;
3738
currentCount = 0;
39+
enumerationDone = false;
3840
CountMinusOne = Math.Max(Count - 1, 0);
3941
}
4042

@@ -52,11 +54,12 @@ public readonly SpanSplitWithCountEnumerator<T> GetEnumerator()
5254
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
5355
public bool MoveNext()
5456
{
55-
ReadOnlySpan<T> span = Span;
56-
if(span.IsEmpty)
57+
if(enumerationDone)
5758
{
5859
return false;
5960
}
61+
62+
ReadOnlySpan<T> span = Span;
6063
if(currentCount == Count)
6164
{
6265
return false;
@@ -84,7 +87,7 @@ public bool MoveNext()
8487
}
8588
if(index == -1 || index >= span.Length)
8689
{
87-
Span = ReadOnlySpan<T>.Empty;
90+
enumerationDone = true;
8891
Current = span;
8992
return true;
9093
}

src/Enumerators/SplitAny/SpanSplitAnyEnumerator.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace SpanExtensions.Enumerators
1111
{
1212
ReadOnlySpan<T> Span;
1313
readonly ReadOnlySpan<T> Delimiters;
14+
bool enumerationDone;
1415

1516
/// <summary>
1617
/// Gets the element in the collection at the current position of the enumerator.
@@ -27,6 +28,7 @@ public SpanSplitAnyEnumerator(ReadOnlySpan<T> source, ReadOnlySpan<T> delimiters
2728
Span = source;
2829
Delimiters = delimiters;
2930
Current = default;
31+
enumerationDone = false;
3032
}
3133

3234
/// <summary>
@@ -43,16 +45,17 @@ public readonly SpanSplitAnyEnumerator<T> GetEnumerator()
4345
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
4446
public bool MoveNext()
4547
{
46-
ReadOnlySpan<T> span = Span;
47-
if(span.IsEmpty)
48+
if(enumerationDone)
4849
{
4950
return false;
5051
}
52+
53+
ReadOnlySpan<T> span = Span;
5154
int index = span.IndexOfAny(Delimiters);
5255

5356
if(index == -1 || index >= span.Length)
5457
{
55-
Span = ReadOnlySpan<T>.Empty;
58+
enumerationDone = true;
5659
Current = span;
5760
return true;
5861
}

src/Enumerators/SplitAny/SpanSplitAnyStringSplitOptionsEnumerator.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public ref struct SpanSplitAnyStringSplitOptionsEnumerator
1010
ReadOnlySpan<char> Span;
1111
readonly ReadOnlySpan<char> Delimiters;
1212
readonly StringSplitOptions Options;
13+
bool enumerationDone;
1314

1415
/// <summary>
1516
/// Gets the element in the collection at the current position of the enumerator.
@@ -28,6 +29,7 @@ public SpanSplitAnyStringSplitOptionsEnumerator(ReadOnlySpan<char> source, ReadO
2829
Delimiters = delimiters;
2930
Options = options;
3031
Current = default;
32+
enumerationDone = false;
3133
}
3234

3335
/// <summary>
@@ -44,16 +46,17 @@ public readonly SpanSplitAnyStringSplitOptionsEnumerator GetEnumerator()
4446
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
4547
public bool MoveNext()
4648
{
47-
ReadOnlySpan<char> span = Span;
48-
if(span.IsEmpty)
49+
if(enumerationDone)
4950
{
5051
return false;
5152
}
53+
54+
ReadOnlySpan<char> span = Span;
5255
int index = span.IndexOfAny(Delimiters);
5356

5457
if(index == -1 || index >= span.Length)
5558
{
56-
Span = ReadOnlySpan<char>.Empty;
59+
enumerationDone = true;
5760
Current = span;
5861
return true;
5962
}
@@ -70,8 +73,20 @@ public bool MoveNext()
7073
if(Current.IsEmpty)
7174
{
7275
Span = span[(index + 1)..];
76+
if(Span.IsEmpty)
77+
{
78+
enumerationDone = true;
79+
return false;
80+
}
7381
return MoveNext();
7482
}
83+
84+
Span = span[(index + 1)..];
85+
if(Span.IsEmpty)
86+
{
87+
enumerationDone = true;
88+
}
89+
return true;
7590
}
7691
Span = span[(index + 1)..];
7792
return true;

src/Enumerators/SplitAny/SpanSplitAnyStringSplitOptionsWithCountEnumerator.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public ref struct SpanSplitAnyStringSplitOptionsWithCountEnumerator
1313
readonly int Count;
1414
readonly CountExceedingBehaviour CountExceedingBehaviour;
1515
int currentCount;
16+
bool enumerationDone;
1617
readonly int CountMinusOne;
1718

1819
/// <summary>
@@ -37,6 +38,7 @@ public SpanSplitAnyStringSplitOptionsWithCountEnumerator(ReadOnlySpan<char> sour
3738
CountExceedingBehaviour = countExceedingBehaviour;
3839
Current = default;
3940
currentCount = 0;
41+
enumerationDone = false;
4042
CountMinusOne = Math.Max(Count - 1, 0);
4143
}
4244

@@ -54,11 +56,12 @@ public readonly SpanSplitAnyStringSplitOptionsWithCountEnumerator GetEnumerator(
5456
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
5557
public bool MoveNext()
5658
{
57-
ReadOnlySpan<char> span = Span;
58-
if(span.IsEmpty)
59+
if(enumerationDone)
5960
{
6061
return false;
6162
}
63+
64+
ReadOnlySpan<char> span = Span;
6265
if(currentCount == Count)
6366
{
6467
return false;
@@ -87,7 +90,7 @@ public bool MoveNext()
8790
}
8891
if(index == -1 || index >= span.Length)
8992
{
90-
Span = ReadOnlySpan<char>.Empty;
93+
enumerationDone = true;
9194
Current = span;
9295
return true;
9396
}
@@ -105,8 +108,20 @@ public bool MoveNext()
105108
if(Current.IsEmpty)
106109
{
107110
Span = span[(index + 1)..];
111+
if(Span.IsEmpty)
112+
{
113+
enumerationDone = true;
114+
return false;
115+
}
108116
return MoveNext();
109117
}
118+
119+
Span = span[(index + 1)..];
120+
if(Span.IsEmpty)
121+
{
122+
enumerationDone = true;
123+
}
124+
return true;
110125
}
111126
Span = span[(index + 1)..];
112127
return true;

src/Enumerators/SplitAny/SpanSplitAnyWithCountEnumerator.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace SpanExtensions.Enumerators
1313
readonly int Count;
1414
readonly CountExceedingBehaviour CountExceedingBehaviour;
1515
int currentCount;
16+
bool enumerationDone;
1617
readonly int CountMinusOne;
1718

1819
/// <summary>
@@ -35,6 +36,7 @@ public SpanSplitAnyWithCountEnumerator(ReadOnlySpan<T> source, ReadOnlySpan<T> d
3536
CountExceedingBehaviour = countExceedingBehaviour;
3637
Current = default;
3738
currentCount = 0;
39+
enumerationDone = false;
3840
CountMinusOne = Math.Max(Count - 1, 0);
3941
}
4042

@@ -52,11 +54,12 @@ public readonly SpanSplitAnyWithCountEnumerator<T> GetEnumerator()
5254
/// <returns><see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the enumerator has passed the end of the collection.</returns>
5355
public bool MoveNext()
5456
{
55-
ReadOnlySpan<T> span = Span;
56-
if(span.IsEmpty)
57+
if(enumerationDone)
5758
{
5859
return false;
5960
}
61+
62+
ReadOnlySpan<T> span = Span;
6063
if(currentCount == Count)
6164
{
6265
return false;
@@ -84,7 +87,7 @@ public bool MoveNext()
8487
}
8588
if(index == -1 || index >= span.Length)
8689
{
87-
Span = ReadOnlySpan<T>.Empty;
90+
enumerationDone = true;
8891
Current = span;
8992
return true;
9093
}

0 commit comments

Comments
 (0)