Skip to content

Commit

Permalink
refs and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonCropp committed Mar 27, 2024
1 parent b5df399 commit a9eb87a
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 17 deletions.
32 changes: 16 additions & 16 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ If, however, `InternalsVisibleTo` is being used to expose APIs (for example to t
Reference: [Module Initializers](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/module-initializers)

<!-- snippet: ModuleInitializerAttribute -->
<a id='snippet-moduleinitializerattribute'></a>
<a id='snippet-ModuleInitializerAttribute'></a>
```cs
static bool InitCalled;

Expand All @@ -93,7 +93,7 @@ public void ModuleInitTest() =>
public static void ModuleInit() =>
InitCalled = true;
```
<sup><a href='/src/Tests/ModuleInitSample.cs#L4-L16' title='Snippet source file'>snippet source</a> | <a href='#snippet-moduleinitializerattribute' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/ModuleInitSample.cs#L4-L16' title='Snippet source file'>snippet source</a> | <a href='#snippet-ModuleInitializerAttribute' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand All @@ -102,14 +102,14 @@ public static void ModuleInit() =>
Reference: [init (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init)

<!-- snippet: IsExternalInit -->
<a id='snippet-isexternalinit'></a>
<a id='snippet-IsExternalInit'></a>
```cs
class InitExample
{
public int Member { get; init; }
}
```
<sup><a href='/src/Tests/MyRecord.cs#L1-L8' title='Snippet source file'>snippet source</a> | <a href='#snippet-isexternalinit' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/MyRecord.cs#L1-L8' title='Snippet source file'>snippet source</a> | <a href='#snippet-IsExternalInit' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down Expand Up @@ -138,7 +138,7 @@ Reference: [Nullable reference types](https://learn.microsoft.com/en-us/dotnet/c
Reference: [C# required modifier](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/required)

<!-- snippet: Required -->
<a id='snippet-required'></a>
<a id='snippet-Required'></a>
```cs
public class Person
{
Expand All @@ -151,7 +151,7 @@ public class Person
public required string Name { get; init; }
}
```
<sup><a href='/src/Tests/Required.cs#L2-L13' title='Snippet source file'>snippet source</a> | <a href='#snippet-required' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/Required.cs#L2-L13' title='Snippet source file'>snippet source</a> | <a href='#snippet-Required' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand All @@ -171,7 +171,7 @@ Reference: [SkipLocalsInitAttribute](https://learn.microsoft.com/en-us/dotnet/cs
> the SkipLocalsInit attribute prevents the compiler from setting the .locals init flag when emitting to metadata. The SkipLocalsInit attribute is a single-use attribute and can be applied to a method, a property, a class, a struct, an interface, or a module, but not to an assembly. SkipLocalsInit is an alias for SkipLocalsInitAttribute.
<!-- snippet: SkipLocalsInit -->
<a id='snippet-skiplocalsinit'></a>
<a id='snippet-SkipLocalsInit'></a>
```cs
class SkipLocalsInitSample
{
Expand All @@ -186,7 +186,7 @@ class SkipLocalsInitSample
}
}
```
<sup><a href='/src/UnsafeTests/SkipLocalsInitExample.cs#L1-L16' title='Snippet source file'>snippet source</a> | <a href='#snippet-skiplocalsinit' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/UnsafeTests/SkipLocalsInitExample.cs#L1-L16' title='Snippet source file'>snippet source</a> | <a href='#snippet-SkipLocalsInit' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand All @@ -197,7 +197,7 @@ Reference: [Indices and ranges](https://learn.microsoft.com/en-us/dotnet/csharp/
If consuming in a project that targets net461 or net462, a reference to System.ValueTuple is required. See [References: System.ValueTuple](#systemvaluetuple).

<!-- snippet: IndexRange -->
<a id='snippet-indexrange'></a>
<a id='snippet-IndexRange'></a>
```cs
[TestFixture]
class IndexRangeSample
Expand All @@ -217,7 +217,7 @@ class IndexRangeSample
}
}
```
<sup><a href='/src/Tests/IndexRangeSample.cs#L1-L21' title='Snippet source file'>snippet source</a> | <a href='#snippet-indexrange' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/IndexRangeSample.cs#L1-L21' title='Snippet source file'>snippet source</a> | <a href='#snippet-IndexRange' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down Expand Up @@ -254,7 +254,7 @@ struct UnscopedRefUsage
Reference: [CallerArgumentExpression](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression)

<!-- snippet: CallerArgumentExpression -->
<a id='snippet-callerargumentexpression'></a>
<a id='snippet-CallerArgumentExpression'></a>
```cs
using System.IO;

Expand All @@ -278,7 +278,7 @@ static class GuardUsage
}
}
```
<sup><a href='/src/Tests/Guard.cs#L3-L26' title='Snippet source file'>snippet source</a> | <a href='#snippet-callerargumentexpression' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/Guard.cs#L3-L26' title='Snippet source file'>snippet source</a> | <a href='#snippet-CallerArgumentExpression' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down Expand Up @@ -757,7 +757,7 @@ If using ValueTask APIs and consuming in a project that target `netframework`, `
Given the following class

<!-- snippet: NullabilityTarget -->
<a id='snippet-nullabilitytarget'></a>
<a id='snippet-NullabilityTarget'></a>
```cs
class NullabilityTarget
{
Expand All @@ -766,14 +766,14 @@ class NullabilityTarget
public Dictionary<string, object?> GenericField;
}
```
<sup><a href='/src/Tests/NullabilityTarget.cs#L3-L10' title='Snippet source file'>snippet source</a> | <a href='#snippet-nullabilitytarget' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/NullabilityTarget.cs#L3-L10' title='Snippet source file'>snippet source</a> | <a href='#snippet-NullabilityTarget' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


### NullabilityInfoContext

<!-- snippet: NullabilityUsage -->
<a id='snippet-nullabilityusage'></a>
<a id='snippet-NullabilityUsage'></a>
```cs
[Test]
public void Test()
Expand All @@ -796,7 +796,7 @@ public void Test()
Assert.AreEqual(NullabilityState.Nullable, genericInfo.GenericTypeArguments[1].ReadState);
}
```
<sup><a href='/src/Tests/NullabilitySamples.cs#L6-L29' title='Snippet source file'>snippet source</a> | <a href='#snippet-nullabilityusage' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Tests/NullabilitySamples.cs#L6-L29' title='Snippet source file'>snippet source</a> | <a href='#snippet-NullabilityUsage' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down
52 changes: 51 additions & 1 deletion src/Polyfill/Polyfill_Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#pragma warning disable

#if FeatureMemory && (NETFRAMEWORK || NETSTANDARD || NETCOREAPP2X)
#if FeatureMemory

using System;
using System.Collections.Generic;
Expand All @@ -12,6 +12,55 @@

static partial class Polyfill
{
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3X || NET5_0_OR_GREATER
/// <summary>
/// Parses the source <see cref="ReadOnlySpan{Char}"/> for the specified <paramref name="separator"/>, populating the <paramref name="destination"/> span
/// with <see cref="Range"/> instances representing the regions between the separators.
/// </summary>
/// <param name="source">The source span to parse.</param>
/// <param name="destination">The destination span into which the resulting ranges are written.</param>
/// <param name="separator">A character that delimits the regions in this instance.</param>
/// <param name="options">A bitwise combination of the enumeration values that specifies whether to trim whitespace and include empty ranges.</param>
/// <returns>The number of ranges written into <paramref name="destination"/>.</returns>
/// <remarks>
/// <para>
/// Delimiter characters are not included in the elements of the returned array.
/// </para>
/// <para>
/// If the <paramref name="destination"/> span is empty, or if the <paramref name="options"/> specifies <see cref="StringSplitOptions.RemoveEmptyEntries"/> and <paramref name="source"/> is empty,
/// or if <paramref name="options"/> specifies both <see cref="StringSplitOptions.RemoveEmptyEntries"/> and <see cref="StringSplitOptions.TrimEntries"/> and the <paramref name="source"/> is
/// entirely whitespace, no ranges are written to the destination.
/// </para>
/// <para>
/// If the span does not contain <paramref name="separator"/>, or if <paramref name="destination"/>'s length is 1, a single range will be output containing the entire <paramref name="source"/>,
/// subject to the processing implied by <paramref name="options"/>.
/// </para>
/// <para>
/// If there are more regions in <paramref name="source"/> than will fit in <paramref name="destination"/>, the first <paramref name="destination"/> length minus 1 ranges are
/// stored in <paramref name="destination"/>, and a range for the remainder of <paramref name="source"/> is stored in <paramref name="destination"/>.
/// </para>
/// </remarks>
public static int Split(this ReadOnlySpan<char> source, Span<Range> destination, char separator, StringSplitOptions options = StringSplitOptions.None)
{
var foundIndexes = new List<int>();

var searchSpan = source;
while (searchSpan.Length > 0)
{
searchSpan.IndexOf(separator);
if()
}
for (int i = source.IndexOf('a'); i > -1; i = s.IndexOf('a', i + 1))
{
// for loop end when i=-1 ('a' not found)
foundIndexes.Add(i);
}
string.CheckStringSplitOptions(options);

return SplitCore(source, destination, new ReadOnlySpan<char>(in separator), default, isAny: true, options);
}
#endif
#if NETFRAMEWORK || NETSTANDARD || NETCOREAPP2X
/// <summary>
/// Indicates whether a specified value is found in a read-only span. Values are compared using IEquatable{T}.Equals(T).
/// </summary>
Expand Down Expand Up @@ -131,6 +180,7 @@ public static bool EndsWith(
this Span<char> target,
string other) =>
target.EndsWith(other.AsSpan());
#endif
}

#endif
15 changes: 15 additions & 0 deletions src/Tests/PolyfillTests_Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ public void ReadOnlySpan_ZeroLengthContains()
Assert.False(found);
}

#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3X || NET5_0_OR_GREATER
[Test]
public void CharSpan_Split()
{
var span = "Hello,World,This,Is,A,Test".AsSpan();

Span<Range> ranges = stackalloc Range[10];

int partsCount = span.Split(ranges, ',', StringSplitOptions.None);

Assert.Equals(6, partsCount);
Assert.Equals("Hello", ranges[0]);
}
#endif

[Test]
public void ReadOnlySpan_TestContains()
{
Expand Down

0 comments on commit a9eb87a

Please sign in to comment.