Skip to content

Commit a014e3a

Browse files
authored
Merge pull request #21 from draconware-dev/dev
Version 1.4
2 parents d9bd5c5 + fef825e commit a014e3a

File tree

61 files changed

+3315
-497
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3315
-497
lines changed

.editorconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ csharp_style_var_elsewhere = false:suggestion
5151
dotnet_diagnostic.CA1001.severity = warning
5252
dotnet_diagnostic.CA1309.severity = warning
5353
dotnet_diagnostic.CA1510.severity = none
54-
csharp_style_prefer_primary_constructors = false:error
54+
csharp_style_prefer_primary_constructors = false:suggestion
5555
dotnet_diagnostic.CA1311.severity = warning
5656
dotnet_diagnostic.SYSLIB1054.severity = warning
5757
dotnet_diagnostic.CA1805.severity = suggestion
@@ -115,7 +115,7 @@ dotnet_style_object_initializer = true:suggestion
115115
dotnet_style_collection_initializer = true:suggestion
116116
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
117117
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
118-
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
118+
dotnet_style_prefer_conditional_expression_over_return = false:suggestion
119119
dotnet_style_operator_placement_when_wrapping = beginning_of_line
120120
tab_width = 4
121121
indent_size = 4

.gitattributes

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
* text=auto
2+
3+
*.cs text diff=csharp
4+
5+
*.sln text eol=crlf merge=binary
6+
*.csproj merge=binary

.github/workflows/format.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
name: Format
3+
4+
on:
5+
push:
6+
branches: [ "dev" ]
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
format:
13+
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Setup .NET
19+
uses: actions/setup-dotnet@v4
20+
with:
21+
dotnet-version: 8.0.x
22+
- name: Restore dependencies
23+
run: dotnet restore
24+
- name: Build
25+
run: dotnet build --no-restore
26+
- name: Format
27+
run: dotnet format style
28+
- name: Commit & Push
29+
run: |
30+
git config --global user.name "github-actions[bot]"
31+
git config --global user.email "github-actions[bot]@user.noreply.github.com"
32+
git commit -a -m"formatted code" || true
33+
git push

.github/workflows/publish.yml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
name: .NET
3+
4+
on:
5+
push:
6+
branches: [ "main" ]
7+
8+
jobs:
9+
publish:
10+
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
- name: Setup .NET
16+
uses: actions/setup-dotnet@v4
17+
with:
18+
dotnet-version: 8.0.x
19+
- name: Restore dependencies
20+
run: dotnet restore
21+
- name: Build
22+
run: dotnet build --no-restore
23+
- name: Pack
24+
run: dotnet pack --no-build --include-symbols -c Release -p:SymbolPackageFormat=snupkg -o ${{github.workspace}}/Packages
25+
- name: Upload Artifact
26+
uses: actions/upload-artifact@v4
27+
with:
28+
name: nupkg
29+
path: |
30+
${{github.workspace}}/Packages/*.nupkg
31+
${{github.workspace}}/Packages/*.snupkg ,.
32+
- name: Download Artifact
33+
uses: actions/download-artifact@v4
34+
with:
35+
name: nupkg
36+
path: |
37+
${{github.workspace}}/Packages/*.nupkg
38+
${{github.workspace}}/Packages/*.snupkg
39+
- name: Extract Version
40+
id: extract_version
41+
uses: mavrosxristoforos/[email protected]
42+
with:
43+
xml-file: '{{github.workspace}}/src/SpanExtensions.csproj'
44+
xpath: '/Project//PropertyGroup//Version'
45+
- name: Store Environment Variable
46+
run: echo "VERSION=v${{ steps.extract_version.outputs.info }}" >> $GITHUB_ENV
47+
- name: Download release notes
48+
run: curl -o release-notes.md https://drive.google.com/uc?export=download&id=1LdP8rvPZ9ra4mc4vmv3smcDwVD96Zwn8
49+
- name: Create Tag
50+
run: |
51+
git tag -a ${{ env.VERSION }} -m"${{ env.VERSION }}"
52+
git push origin ${{ env.VERSION }}
53+
- name: Create Release
54+
run: gh release create ${{ env.VERSION }} --title ${{ env.VERSION }} --notes-file release-notes.md ${{github.workspace}}/Packages/*.nupkg ${{github.workspace}}/Packages/*.snupkg
55+
env:
56+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57+
- name: Push To Nuget
58+
run: dotnet nuget push "${{github.workspace}}/Packages/*.nupkg" -k ${{secrets.NUGET_API_KEY_SPANEXTENSIONS}} -s https://api.nuget.org/v3/index.json --skip-duplicate

.github/workflows/dotnet.yml renamed to .github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ on:
55
push:
66
branches: [ "main" ]
77
pull_request:
8-
branches: [ "dev" ]
8+
branches: [ "dev", "main" ]
99
paths:
1010
- '**.cs'
1111
- '**.csproj'
1212

1313
jobs:
14-
build:
14+
test:
1515

1616
runs-on: ubuntu-latest
1717

@@ -26,4 +26,4 @@ jobs:
2626
- name: Build
2727
run: dotnet build --no-restore
2828
- name: Test
29-
run: dotnet test --no-build --verbosity normal
29+
run: dotnet test --no-build --verbosity normal --filter FullyQualifiedName!~SpanExtensions.Tests.Fuzzing

Changelog.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,27 @@
33
All notable changes to this project will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6+
and this project adheres not (yet) to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
9+
## [1.4] - 2024-9-3
10+
11+
### Added
12+
13+
- `(Readonly-)Span<T>.Count()`
14+
- `(Readonly-)Span<T>.Count(Predicate<T> predicate)`
15+
16+
### Changed
17+
18+
- `Split` to throw an `ArgumentException` instead of an `InvalidCountExceedingBehaviourException`
19+
20+
### Removed
21+
22+
- `InvalidCountExceedingBehaviourException`
23+
24+
### Fixed
25+
26+
- various issues with `Split` (https://github.com/draconware-dev/SpanExtensions.Net/pull/11)
727

828
## [1.3] - 2024-3-19
929

SpanExtensions.sln

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ VisualStudioVersion = 17.5.33627.172
55
MinimumVisualStudioVersion = 10.0.40219.1
66
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SpanExtensions", "src\SpanExtensions.csproj", "{75DE5AFD-663E-415D-9B95-6BC513BD4A07}"
77
EndProject
8+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTests", "tests\unit-tests\UnitTests.csproj", "{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}"
9+
EndProject
10+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PerformanceTests", "tests\Performance\PerformanceTests.csproj", "{CE74F420-1038-4E51-AC31-00DA964CC4F5}"
11+
EndProject
812
Global
913
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1014
Debug|Any CPU = Debug|Any CPU
@@ -15,6 +19,14 @@ Global
1519
{75DE5AFD-663E-415D-9B95-6BC513BD4A07}.Debug|Any CPU.Build.0 = Debug|Any CPU
1620
{75DE5AFD-663E-415D-9B95-6BC513BD4A07}.Release|Any CPU.ActiveCfg = Release|Any CPU
1721
{75DE5AFD-663E-415D-9B95-6BC513BD4A07}.Release|Any CPU.Build.0 = Release|Any CPU
22+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Debug|Any CPU.Build.0 = Debug|Any CPU
24+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Release|Any CPU.ActiveCfg = Release|Any CPU
25+
{B48A0293-A7FF-4E39-8F8D-57B6F824D70F}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{CE74F420-1038-4E51-AC31-00DA964CC4F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{CE74F420-1038-4E51-AC31-00DA964CC4F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{CE74F420-1038-4E51-AC31-00DA964CC4F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{CE74F420-1038-4E51-AC31-00DA964CC4F5}.Release|Any CPU.Build.0 = Release|Any CPU
1830
EndGlobalSection
1931
GlobalSection(SolutionProperties) = preSolution
2032
HideSolutionNode = FALSE

src/CountExceedingBehaviour.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
namespace SpanExtensions
22
{
33
/// <summary>
4-
/// Defines the behaviour of a split operation when there are more split instances than there may be.
4+
/// Defines the behaviour of a split operation when there are more split instances than there may be.
55
/// </summary>
66
public enum CountExceedingBehaviour
77
{
88
/// <summary>
9-
/// The last element returned will be all the remaining elements appended as one.
9+
/// The last split returned will include all the remaining elements.
1010
/// </summary>
1111
AppendRemainingElements,
1212
/// <summary>
13-
/// Every split instance more than permitted will not be returned.
13+
/// Splits after the desired split count will be cut.
1414
/// </summary>
1515
CutRemainingElements
1616
}

src/Enumerators/Split/SpanSplitEnumerator.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ namespace SpanExtensions.Enumerators
1010
{
1111
ReadOnlySpan<T> Span;
1212
readonly T Delimiter;
13-
bool enumerationDone;
13+
const int DelimiterLength = 1;
14+
bool EnumerationDone;
1415

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

3334
/// <summary>
@@ -44,22 +45,25 @@ public readonly SpanSplitEnumerator<T> GetEnumerator()
4445
/// <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>
4546
public bool MoveNext()
4647
{
47-
if(enumerationDone)
48+
if(EnumerationDone)
4849
{
4950
return false;
5051
}
5152

52-
ReadOnlySpan<T> span = Span;
53-
int index = span.IndexOf(Delimiter);
53+
int delimiterIndex = Span.IndexOf(Delimiter);
5454

55-
if(index == -1 || index >= span.Length)
55+
if(delimiterIndex == -1)
5656
{
57-
enumerationDone = true;
58-
Current = span;
57+
EnumerationDone = true;
58+
59+
Current = Span;
60+
5961
return true;
6062
}
61-
Current = span[..index];
62-
Span = span[(index + 1)..];
63+
64+
Current = Span[..delimiterIndex];
65+
Span = Span[(delimiterIndex + DelimiterLength)..];
66+
6367
return true;
6468
}
6569
}

src/Enumerators/Split/SpanSplitStringSplitOptionsEnumerator.cs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ public ref struct SpanSplitStringSplitOptionsEnumerator
99
{
1010
ReadOnlySpan<char> Span;
1111
readonly char Delimiter;
12-
readonly StringSplitOptions Options;
13-
bool enumerationDone;
12+
const int DelimiterLength = 1;
13+
readonly bool TrimEntries;
14+
readonly bool RemoveEmptyEntries;
15+
bool EnumerationDone;
1416

1517
/// <summary>
1618
/// Gets the element in the collection at the current position of the enumerator.
@@ -25,11 +27,14 @@ public ref struct SpanSplitStringSplitOptionsEnumerator
2527
/// <param name="options">A bitwise combination of the enumeration values that specifies whether to trim results and include empty results.</param>
2628
public SpanSplitStringSplitOptionsEnumerator(ReadOnlySpan<char> source, char delimiter, StringSplitOptions options)
2729
{
30+
ExceptionHelpers.ThrowIfInvalid(options, nameof(options));
31+
2832
Span = source;
2933
Delimiter = delimiter;
30-
Options = options;
34+
TrimEntries = options.HasFlag((StringSplitOptions)2); // StringSplitOptions.TrimEntries
35+
RemoveEmptyEntries = options.HasFlag(StringSplitOptions.RemoveEmptyEntries);
36+
EnumerationDone = false;
3137
Current = default;
32-
enumerationDone = false;
3338
}
3439

3540
/// <summary>
@@ -46,49 +51,44 @@ public readonly SpanSplitStringSplitOptionsEnumerator GetEnumerator()
4651
/// <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>
4752
public bool MoveNext()
4853
{
49-
if(enumerationDone)
54+
if(EnumerationDone)
5055
{
5156
return false;
5257
}
5358

54-
ReadOnlySpan<char> span = Span;
55-
int index = span.IndexOf(Delimiter);
56-
57-
if(index == -1 || index >= span.Length)
58-
{
59-
enumerationDone = true;
60-
Current = span;
61-
return true;
62-
}
63-
Current = span[..index];
64-
#if NET5_0_OR_GREATER
65-
if(Options.HasFlag(StringSplitOptions.TrimEntries))
66-
{
67-
Current = Current.Trim();
68-
}
69-
#endif
70-
if(Options.HasFlag(StringSplitOptions.RemoveEmptyEntries))
59+
while(true) // if RemoveEmptyEntries options flag is set, repeat until a non-empty span is found, or the end is reached
7160
{
72-
if(Current.IsEmpty)
61+
int delimiterIndex = Span.IndexOf(Delimiter);
62+
63+
if(delimiterIndex == -1)
7364
{
74-
Span = span[(index + 1)..];
75-
if(Span.IsEmpty)
65+
EnumerationDone = true;
66+
67+
Current = Span;
68+
69+
if(TrimEntries)
7670
{
77-
enumerationDone = true;
78-
return false;
71+
Current = Current.Trim();
7972
}
80-
return MoveNext();
73+
74+
return !(RemoveEmptyEntries && Current.IsEmpty);
75+
}
76+
77+
Current = Span[..delimiterIndex];
78+
Span = Span[(delimiterIndex + DelimiterLength)..];
79+
80+
if(TrimEntries)
81+
{
82+
Current = Current.Trim();
8183
}
8284

83-
Span = span[(index + 1)..];
84-
if(Span.IsEmpty)
85+
if(RemoveEmptyEntries && Current.IsEmpty)
8586
{
86-
enumerationDone = true;
87+
continue;
8788
}
89+
8890
return true;
8991
}
90-
Span = span[(index + 1)..];
91-
return true;
9292
}
9393
}
9494
}

0 commit comments

Comments
 (0)