Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres not (yet) to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.5.1] - 2024-12-14

### Fixed

- incorrect ranges returned by the range-based Split method for versions prior to .Net 9.

### Changed

- moved MemoryExtensions containing range-based Split method for versions prior to .Net 9 from `System` to `SpanExtensions`.
- grammatical issues in some documentation comments.

## [1.5] - 2024-11-12

### Added
Expand Down
45 changes: 30 additions & 15 deletions src/Enumerators/System/SpanSplitEnumerator.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Buffers;
using System;
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;

#if !NET9_0_OR_GREATER

namespace System
namespace SpanExtensions
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public static partial class MemoryExtensions
Expand All @@ -23,27 +24,35 @@ public static partial class MemoryExtensions
readonly SearchValues<T> SearchValues = null!;
#endif

int currentStartIndex;
int currentEndIndex;
int nextStartIndex;
/// <summary>
/// Gets the current element of the enumeration.
/// </summary>
/// <returns>Returns a <see cref="Range"/> instance that indicates the bounds of the current element withing the source span.</returns>
public Range Current { get; internal set; }
/// <returns>Returns a <see cref="Range"/> instance that indicates the bounds of the current element within the source span.</returns>
public readonly Range Current => new Range(currentStartIndex, currentEndIndex);

internal SpanSplitEnumerator(ReadOnlySpan<T> source, T delimiter)
{
Span = source;
Delimiter = delimiter;
Current = new Range(0, 0);
DelimiterSpan = default;
mode = SpanSplitEnumeratorMode.Delimiter;
currentStartIndex = 0;
currentEndIndex = 0;
nextStartIndex = 0;
}

internal SpanSplitEnumerator(ReadOnlySpan<T> source, ReadOnlySpan<T> delimiter, SpanSplitEnumeratorMode mode)
{
Span = source;
DelimiterSpan = delimiter;
Current = new Range(0, 0);
Delimiter = default!;
this.mode = mode;
currentStartIndex = 0;
currentEndIndex = 0;
nextStartIndex = 0;
}

#if NET8_0
Expand All @@ -52,9 +61,11 @@ internal SpanSplitEnumerator(ReadOnlySpan<T> source, SearchValues<T> searchValue
Span = source;
Delimiter = default!;
SearchValues = searchValues;
Current = new Range(0, 0);
DelimiterSpan = default;
mode = SpanSplitEnumeratorMode.Delimiter;
currentStartIndex = 0;
currentEndIndex = 0;
nextStartIndex = 0;
}
#endif
/// <summary>
Expand All @@ -77,17 +88,17 @@ public bool MoveNext()
switch(mode)
{
case SpanSplitEnumeratorMode.Delimiter:
index = Span[Current.Start..].IndexOf(Delimiter);
index = Span[nextStartIndex..].IndexOf(Delimiter);
length = 1;
break;

case SpanSplitEnumeratorMode.Any:
index = Span[Current.Start..].IndexOfAny(DelimiterSpan);
index = Span[nextStartIndex..].IndexOfAny(DelimiterSpan);
length = 1;
break;

case SpanSplitEnumeratorMode.Sequence:
index = Span[Current.Start..].IndexOf(DelimiterSpan);
index = Span[nextStartIndex..].IndexOf(DelimiterSpan);
length = DelimiterSpan.Length;
break;

Expand All @@ -98,23 +109,28 @@ public bool MoveNext()

#if NET8_0
case SpanSplitEnumeratorMode.SearchValues:
index = Span[Current.Start..].IndexOfAny(SearchValues);
index = Span[nextStartIndex..].IndexOfAny(SearchValues);
length = 1;
break;
#endif
default:
return false;
}

currentStartIndex = nextStartIndex;

if(index < 0)
{
Current = new Range(Span.Length, Span.Length);
currentEndIndex = Span.Length;
nextStartIndex = Span.Length;

mode = (SpanSplitEnumeratorMode)(-1);
return true;
}

Current = new Range(Current.End.Value + length, Current.Start.Value + index);

currentEndIndex = currentStartIndex + index;
nextStartIndex = currentEndIndex + length;

return true;
}
}
Expand All @@ -129,5 +145,4 @@ internal enum SpanSplitEnumeratorMode
}
}
}

#endif
5 changes: 3 additions & 2 deletions src/Extensions/ReadOnlySpan/Span/Split.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Buffers;
using System;
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;

#if !NET9_0_OR_GREATER

namespace System
namespace SpanExtensions
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public static partial class MemoryExtensions
Expand Down
5 changes: 3 additions & 2 deletions src/Extensions/Span/Span/Split.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Buffers;
using System;
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;

#if !NET9_0_OR_GREATER

namespace System
namespace SpanExtensions
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
public static partial class MemoryExtensions
Expand Down
108 changes: 54 additions & 54 deletions src/SpanExtensions.csproj
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net9.0;net8.0;net7.0;net6.0;net5.0;netstandard2.1</TargetFrameworks>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<Platforms>AnyCPU</Platforms>
<Title>Span Extensions</Title>
<Authors>dragon-cs</Authors>
<Company>draconware</Company>
<Description>
ReadonlySpan&lt;T&gt; and Span&lt;T&gt; are great Types in C#, but unfortunately working with them can sometimes be sort of a hassle and some use cases seem straight up impossible, even though they are not.
<PropertyGroup>
<TargetFrameworks>net9.0;net8.0;net7.0;net6.0;net5.0;netstandard2.1</TargetFrameworks>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<Platforms>AnyCPU</Platforms>
<Title>Span Extensions</Title>
<Authors>dragon-cs</Authors>
<Company>draconware</Company>
<Description>
ReadonlySpan&lt;T&gt; and Span&lt;T&gt; are great Types in C#, but unfortunately working with them can sometimes be sort of a hassle and some use cases seem straight up impossible, even though they are not.

SpanExtensions.Net aims to help developers use ReadonlySpan&lt;T&gt; and Span&lt;T&gt; more productively, efficiently and safely and write overall more performant Programs.
SpanExtensions.Net aims to help developers use ReadonlySpan&lt;T&gt; and Span&lt;T&gt; more productively, efficiently and safely and write overall more performant Programs.

Never again switch back to using string instead of ReadonlySpan&lt;T&gt;, just because the method you seek is not supported.
</Description>
<RepositoryUrl>https://github.com/draconware-dev/SpanExtensions.Net</RepositoryUrl>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<Copyright>Copyright (c) 2024 draconware-dev</Copyright>
<PackageTags>Span;Performance;Extension;String</PackageTags>
<PackageReleaseNotes>https://github.com/draconware-dev/SpanExtensions.Net/blob/main/Changelog.md</PackageReleaseNotes>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Version>1.5</Version>
<PackageId>SpanExtensions.Net</PackageId>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>
Never again switch back to using string instead of ReadonlySpan&lt;T&gt;, just because the method you seek is not supported.
</Description>
<RepositoryUrl>https://github.com/draconware-dev/SpanExtensions.Net</RepositoryUrl>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<Copyright>Copyright (c) 2024 draconware-dev</Copyright>
<PackageTags>Span;Performance;Extension;String</PackageTags>
<PackageReleaseNotes>https://github.com/draconware-dev/SpanExtensions.Net/blob/main/Changelog.md</PackageReleaseNotes>
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<Version>1.5.1</Version>
<PackageId>SpanExtensions.Net</PackageId>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageIcon>icon.png</PackageIcon>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>portable</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DebugType>portable</DebugType>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugType>portable</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugType>portable</DebugType>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>portable</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DebugType>portable</DebugType>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebugType>portable</DebugType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<DebugType>portable</DebugType>
</PropertyGroup>

<ItemGroup>
<None Include="README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\LICENSE">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="README.md">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
<None Include="..\LICENSE">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

<ItemGroup>
<None Include="icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>
<ItemGroup>
<None Include="icon.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

</Project>
Loading