-Microsoft Visual Studio Solution File, Format Version 12.00
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.6.33316.92
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{7746BFD6-E6D6-4703-AA2D-43380B5DEA22}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{6A54FACA-933E-4C1D-92AB-1A5506CFC212}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Checked|Any CPU = Checked|Any CPU
+ Checked|x64 = Checked|x64
+ Checked|x86 = Checked|x86
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
- Checked|Any CPU = Checked|Any CPU
- Checked|x64 = Checked|x64
- Checked|x86 = Checked|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|Any CPU.ActiveCfg = Checked|x64
+ {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|Any CPU.Build.0 = Checked|x64
+ {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x64.ActiveCfg = Checked|x64
+ {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x64.Build.0 = Checked|x64
+ {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x86.ActiveCfg = Checked|x86
+ {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x86.Build.0 = Checked|x86
{7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Debug|Any CPU.ActiveCfg = Debug|x64
{7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Debug|Any CPU.Build.0 = Debug|x64
{7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Debug|x64.ActiveCfg = Debug|x64
{7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Release|x64.Build.0 = Release|x64
{7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Release|x86.ActiveCfg = Release|x86
{7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Release|x86.Build.0 = Release|x86
- {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|Any CPU.ActiveCfg = Checked|x64
- {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|Any CPU.Build.0 = Checked|x64
- {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x64.ActiveCfg = Checked|x64
- {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x64.Build.0 = Checked|x64
- {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x86.ActiveCfg = Checked|x86
- {7746BFD6-E6D6-4703-AA2D-43380B5DEA22}.Checked|x86.Build.0 = Checked|x86
+ {6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Checked|x86.ActiveCfg = Debug|Any CPU
{6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Debug|x64.ActiveCfg = Debug|Any CPU
{6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Release|x64.Build.0 = Release|Any CPU
{6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Release|x86.ActiveCfg = Release|Any CPU
{6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Release|x86.Build.0 = Release|Any CPU
- {6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Checked|x64.ActiveCfg = Debug|Any CPU
- {6A54FACA-933E-4C1D-92AB-1A5506CFC212}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {9112BAE3-344D-4DD0-ADC9-478D82B84584}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {9112BAE3-344D-4DD0-ADC9-478D82B84584}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {9112BAE3-344D-4DD0-ADC9-478D82B84584}.Checked|x86.ActiveCfg = Debug|Any CPU
{9112BAE3-344D-4DD0-ADC9-478D82B84584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9112BAE3-344D-4DD0-ADC9-478D82B84584}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9112BAE3-344D-4DD0-ADC9-478D82B84584}.Debug|x64.ActiveCfg = Debug|Any CPU
{9112BAE3-344D-4DD0-ADC9-478D82B84584}.Release|x64.Build.0 = Release|Any CPU
{9112BAE3-344D-4DD0-ADC9-478D82B84584}.Release|x86.ActiveCfg = Release|Any CPU
{9112BAE3-344D-4DD0-ADC9-478D82B84584}.Release|x86.Build.0 = Release|Any CPU
- {9112BAE3-344D-4DD0-ADC9-478D82B84584}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {9112BAE3-344D-4DD0-ADC9-478D82B84584}.Checked|x64.ActiveCfg = Debug|Any CPU
- {9112BAE3-344D-4DD0-ADC9-478D82B84584}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Checked|x86.ActiveCfg = Debug|Any CPU
{C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Debug|x64.ActiveCfg = Debug|Any CPU
{C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Release|x64.Build.0 = Release|Any CPU
{C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Release|x86.ActiveCfg = Release|Any CPU
{C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Release|x86.Build.0 = Release|Any CPU
- {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Checked|x64.ActiveCfg = Debug|Any CPU
- {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Checked|x86.ActiveCfg = Debug|Any CPU
{C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Debug|x64.ActiveCfg = Debug|Any CPU
{C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Release|x64.Build.0 = Release|Any CPU
{C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Release|x86.ActiveCfg = Release|Any CPU
{C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Release|x86.Build.0 = Release|Any CPU
- {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Checked|x64.ActiveCfg = Debug|Any CPU
- {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {EFF00253-633C-4D2F-86EE-F40C721F6A68}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {EFF00253-633C-4D2F-86EE-F40C721F6A68}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {EFF00253-633C-4D2F-86EE-F40C721F6A68}.Checked|x86.ActiveCfg = Debug|Any CPU
{EFF00253-633C-4D2F-86EE-F40C721F6A68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EFF00253-633C-4D2F-86EE-F40C721F6A68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EFF00253-633C-4D2F-86EE-F40C721F6A68}.Debug|x64.ActiveCfg = Debug|Any CPU
{EFF00253-633C-4D2F-86EE-F40C721F6A68}.Release|x64.Build.0 = Release|Any CPU
{EFF00253-633C-4D2F-86EE-F40C721F6A68}.Release|x86.ActiveCfg = Release|Any CPU
{EFF00253-633C-4D2F-86EE-F40C721F6A68}.Release|x86.Build.0 = Release|Any CPU
- {EFF00253-633C-4D2F-86EE-F40C721F6A68}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {EFF00253-633C-4D2F-86EE-F40C721F6A68}.Checked|x64.ActiveCfg = Debug|Any CPU
- {EFF00253-633C-4D2F-86EE-F40C721F6A68}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Checked|x86.ActiveCfg = Debug|Any CPU
{D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Debug|x64.ActiveCfg = Debug|Any CPU
{D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Release|x64.Build.0 = Release|Any CPU
{D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Release|x86.ActiveCfg = Release|Any CPU
{D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Release|x86.Build.0 = Release|Any CPU
- {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Checked|x64.ActiveCfg = Debug|Any CPU
- {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Checked|x86.ActiveCfg = Debug|Any CPU
{84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Debug|x64.ActiveCfg = Debug|Any CPU
{84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Release|x64.Build.0 = Release|Any CPU
{84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Release|x86.ActiveCfg = Release|Any CPU
{84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Release|x86.Build.0 = Release|Any CPU
- {84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Checked|x64.ActiveCfg = Debug|Any CPU
- {84AD7BF6-D76C-4BEE-9879-5A23150DD3F7}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Checked|x86.ActiveCfg = Debug|Any CPU
{DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Debug|x64.ActiveCfg = Debug|Any CPU
{DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Release|x64.Build.0 = Release|Any CPU
{DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Release|x86.ActiveCfg = Release|Any CPU
{DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Release|x86.Build.0 = Release|Any CPU
- {DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Checked|x64.ActiveCfg = Debug|Any CPU
- {DA7CEED7-1A86-4221-B4AD-4307AB83A31F}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {B773D664-C00B-4DB3-823B-947576EE7A46}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {B773D664-C00B-4DB3-823B-947576EE7A46}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {B773D664-C00B-4DB3-823B-947576EE7A46}.Checked|x86.ActiveCfg = Debug|Any CPU
{B773D664-C00B-4DB3-823B-947576EE7A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B773D664-C00B-4DB3-823B-947576EE7A46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B773D664-C00B-4DB3-823B-947576EE7A46}.Debug|x64.ActiveCfg = Debug|Any CPU
{B773D664-C00B-4DB3-823B-947576EE7A46}.Release|x64.Build.0 = Release|Any CPU
{B773D664-C00B-4DB3-823B-947576EE7A46}.Release|x86.ActiveCfg = Release|Any CPU
{B773D664-C00B-4DB3-823B-947576EE7A46}.Release|x86.Build.0 = Release|Any CPU
- {B773D664-C00B-4DB3-823B-947576EE7A46}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
- {B773D664-C00B-4DB3-823B-947576EE7A46}.Checked|x64.ActiveCfg = Debug|Any CPU
- {B773D664-C00B-4DB3-823B-947576EE7A46}.Checked|x86.ActiveCfg = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7746BFD6-E6D6-4703-AA2D-43380B5DEA22} = {C352AC7D-959D-431F-AF83-2CA506B70D59}
- {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92} = {C352AC7D-959D-431F-AF83-2CA506B70D59}
{6A54FACA-933E-4C1D-92AB-1A5506CFC212} = {FA259C32-B79B-4DE2-9677-055D5D25FA33}
- {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297} = {FA259C32-B79B-4DE2-9677-055D5D25FA33}
{9112BAE3-344D-4DD0-ADC9-478D82B84584} = {7212FBCF-E89D-4065-9DCE-D5F7E5D3EF1D}
- {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE} = {7212FBCF-E89D-4065-9DCE-D5F7E5D3EF1D}
- {B773D664-C00B-4DB3-823B-947576EE7A46} = {7212FBCF-E89D-4065-9DCE-D5F7E5D3EF1D}
+ {C9417154-D8DB-4FF9-9DD8-6B2ED351FC92} = {C352AC7D-959D-431F-AF83-2CA506B70D59}
+ {C2BC6AE7-7E8B-4AA2-8E9F-5D4B9127B297} = {FA259C32-B79B-4DE2-9677-055D5D25FA33}
{EFF00253-633C-4D2F-86EE-F40C721F6A68} = {2BEB1A89-DD2D-42BD-95DD-89860A0C9663}
+ {D0EEF7E0-BD51-4C39-AF4F-DD583D01AEBE} = {7212FBCF-E89D-4065-9DCE-D5F7E5D3EF1D}
{84AD7BF6-D76C-4BEE-9879-5A23150DD3F7} = {2BEB1A89-DD2D-42BD-95DD-89860A0C9663}
{DA7CEED7-1A86-4221-B4AD-4307AB83A31F} = {2BEB1A89-DD2D-42BD-95DD-89860A0C9663}
+ {B773D664-C00B-4DB3-823B-947576EE7A46} = {7212FBCF-E89D-4065-9DCE-D5F7E5D3EF1D}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65DB6A6B-0AAC-4BC2-A61A-641679771DC7}
EndGlobalSection
+ GlobalSection(SharedMSBuildProjectFiles) = preSolution
+ ..\System.Private.CoreLib\src\System.Private.CoreLib.Shared.projitems*{7746bfd6-e6d6-4703-aa2d-43380b5dea22}*SharedItemsImports = 5
+ EndGlobalSection
EndGlobal
public static bool Contains<T>(this System.Span<T> span, T value) where T : System.IEquatable<T>? { throw null; }
public static void CopyTo<T>(this T[]? source, System.Memory<T> destination) { }
public static void CopyTo<T>(this T[]? source, System.Span<T> destination) { }
+ public static int Count<T>(this System.Span<T> span, T value) where T : System.IEquatable<T>? { throw null; }
+ public static int Count<T>(this System.ReadOnlySpan<T> span, T value) where T : System.IEquatable<T>? { throw null; }
+ public static int Count<T>(this System.Span<T> span, System.ReadOnlySpan<T> value) where T : System.IEquatable<T>? { throw null; }
+ public static int Count<T>(this System.ReadOnlySpan<T> span, System.ReadOnlySpan<T> value) where T : System.IEquatable<T>? { throw null; }
public static bool EndsWith(this System.ReadOnlySpan<char> span, System.ReadOnlySpan<char> value, System.StringComparison comparisonType) { throw null; }
public static bool EndsWith<T>(this System.ReadOnlySpan<T> span, System.ReadOnlySpan<T> value) where T : System.IEquatable<T>? { throw null; }
public static bool EndsWith<T>(this System.Span<T> span, System.ReadOnlySpan<T> value) where T : System.IEquatable<T>? { throw null; }
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Xunit;
+
+namespace System.SpanTests
+{
+ public static partial class ReadOnlySpanTests
+ {
+ [Fact]
+ public static void ZeroLengthCount_Int()
+ {
+ Assert.Equal(0, ReadOnlySpan<int>.Empty.Count(0));
+ }
+
+ [Fact]
+ public static void ZeroLengthCount_RosInt()
+ {
+ for (int i = 0; i <= 2; i++)
+ {
+ Assert.Equal(0, ReadOnlySpan<int>.Empty.Count(new int[i]));
+ }
+ }
+
+ [Fact]
+ public static void ZeroLengthNeedleCount_RosInt()
+ {
+ ReadOnlySpan<int> span = new ReadOnlySpan<int>(new int[] { 5, 5, 5, 5, 5 });
+
+ Assert.Equal(0, span.Count<int>(ReadOnlySpan<int>.Empty));
+ }
+
+ [Fact]
+ public static void TestCount_Int()
+ {
+ for (int length = 0; length < 32; length++)
+ {
+ int[] a = new int[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = 10 * (i + 1);
+ }
+ ReadOnlySpan<int> span = new ReadOnlySpan<int>(a);
+
+ for (int targetIndex = 0; targetIndex < length; targetIndex++)
+ {
+ Assert.Equal(1, span.Count(a[targetIndex]));
+ }
+ }
+ }
+
+ [Fact]
+ public static void TestCount_RosInt()
+ {
+ for (int length = 0; length < 32; length++)
+ {
+ int[] a = new int[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = 10 * (i + 1);
+ }
+ ReadOnlySpan<int> span = new ReadOnlySpan<int>(a);
+
+ for (int targetIndex = 0; targetIndex < length - 1; targetIndex++)
+ {
+ Assert.Equal(1, span.Count(new int[] { a[targetIndex], a[targetIndex + 1] }));
+ }
+ }
+ }
+
+ [Fact]
+ public static void TestMultipleCount_Int()
+ {
+ for (int length = 2; length < 32; length++)
+ {
+ int[] a = new int[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = 10 * (i + 1);
+ }
+
+ a[^1] = a[^2] = 5555;
+
+ ReadOnlySpan<int> span = new ReadOnlySpan<int>(a);
+ Assert.Equal(2, span.Count(5555));
+ }
+ }
+
+ [Fact]
+ public static void TestMultipleCount_RosInt()
+ {
+ for (int length = 4; length < 32; length++)
+ {
+ int[] a = new int[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = 10 * (i + 1);
+ }
+ a[0] = a[1] = a[^1] = a[^2] = 5555;
+
+ ReadOnlySpan<int> span = new ReadOnlySpan<int>(a);
+ Assert.Equal(2, span.Count<int>(new int[] { 5555, 5555 }));
+ }
+ }
+
+ [Fact]
+ public static void OnNoMatchForCountMakeSureEveryElementIsCompared_TInt()
+ {
+ for (int length = 0; length < 100; length++)
+ {
+ TIntLog log = new TIntLog();
+
+ TInt[] a = new TInt[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = new TInt(10 * (i + 1), log);
+ }
+ ReadOnlySpan<TInt> span = new ReadOnlySpan<TInt>(a);
+ Assert.Equal(0, span.Count(new TInt(9999, log)));
+
+ // Since we asked for a non-existent value, make sure each element of the array was compared once.
+ // (Strictly speaking, it would not be illegal for Count to compare an element more than once but
+ // that would be a non-optimal implementation and a red flag. So we'll stick with the stricter test.)
+ Assert.Equal(a.Length, log.Count);
+ foreach (TInt elem in a)
+ {
+ int numCompares = log.CountCompares(elem.Value, 9999);
+ Assert.True(numCompares == 1, $"Expected {numCompares} == 1 for element {elem.Value}.");
+ }
+ }
+ }
+
+ [Fact]
+ public static void OnNoMatchForCountMakeSureEveryElementIsCompared_RosTInt()
+ {
+ for (int length = 0; length < 100; length++)
+ {
+ TIntLog log = new TIntLog();
+
+ TInt[] a = new TInt[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = new TInt(10 * (i + 1), log);
+ }
+
+ ReadOnlySpan<TInt> span = new ReadOnlySpan<TInt>(a);
+ Assert.Equal(0, span.Count(new TInt[] { new TInt(9999, log), new TInt(10000, log) }));
+
+ // Since we asked for a non-existent value, make sure each element of the array was compared once.
+ // (Strictly speaking, it would not be illegal for Count to compare an element more than once but
+ // that would be a non-optimal implementation and a red flag. So we'll stick with the stricter test.)
+ if (length > 0)
+ {
+ Assert.Equal(a.Length - 1, log.Count);
+ }
+ for (int i = 0; i < length - 1; i++)
+ {
+ int numCompares = log.CountCompares(a[i].Value, 9999);
+ Assert.True(numCompares == 1, $"Expected {numCompares} == 1 for element {a[i].Value}.");
+
+ numCompares = log.CountCompares(a[i].Value, 10000);
+ Assert.True(numCompares == 0, $"Expected {numCompares} == 0 for element {a[i].Value}.");
+ }
+ }
+ }
+
+ [Fact]
+ public static void MakeSureNoChecksForCountGoOutOfRange_TInt()
+ {
+ const int GuardValue = 77777;
+ const int GuardLength = 50;
+
+ void CheckForOutOfRangeAccess(int x, int y) =>
+ Assert.True(x != GuardValue && y != GuardValue, $"{x} or {y} == {GuardValue}");
+
+ for (int length = 0; length < 100; length++)
+ {
+ TInt[] a = new TInt[GuardLength + length + GuardLength];
+ for (int i = 0; i < a.Length; i++)
+ {
+ a[i] = new TInt(GuardValue, CheckForOutOfRangeAccess);
+ }
+
+ for (int i = 0; i < length; i++)
+ {
+ a[GuardLength + i] = new TInt(10 * (i + 1), CheckForOutOfRangeAccess);
+ }
+
+ ReadOnlySpan<TInt> span = new ReadOnlySpan<TInt>(a, GuardLength, length);
+ Assert.Equal(0, span.Count(new TInt(9999, CheckForOutOfRangeAccess)));
+ }
+ }
+
+ [Fact]
+ public static void MakeSureNoChecksForCountGoOutOfRange_RosTInt()
+ {
+ const int GuardValue = 77777;
+ const int GuardLength = 50;
+
+ void CheckForOutOfRangeAccess(int x, int y) =>
+ Assert.True(x != GuardValue && y != GuardValue, $"{x} or {y} == {GuardValue}");
+
+ for (int length = 0; length < 100; length++)
+ {
+ TInt[] a = new TInt[GuardLength + length + GuardLength];
+ for (int i = 0; i < a.Length; i++)
+ {
+ a[i] = new TInt(GuardValue, CheckForOutOfRangeAccess);
+ }
+
+ for (int i = 0; i < length; i++)
+ {
+ a[GuardLength + i] = new TInt(10 * (i + 1), CheckForOutOfRangeAccess);
+ }
+
+ ReadOnlySpan<TInt> span = new ReadOnlySpan<TInt>(a, GuardLength, length);
+ Assert.Equal(0, span.Count(new TInt[] { new TInt(9999, CheckForOutOfRangeAccess), new TInt(9999, CheckForOutOfRangeAccess) }));
+ }
+ }
+
+ [Fact]
+ public static void ZeroLengthCount_String()
+ {
+ Assert.Equal(0, ReadOnlySpan<string>.Empty.Count("a"));
+ }
+
+ [Fact]
+ public static void ZeroLengthCount_RosString()
+ {
+ Assert.Equal(0, ReadOnlySpan<string>.Empty.Count(new[] { "a", "b" }));
+ }
+
+ [Fact]
+ public static void TestMatchCount_String()
+ {
+ for (int length = 0; length < 32; length++)
+ {
+ string[] a = new string[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = (10 * (i + 1)).ToString();
+ }
+ ReadOnlySpan<string> span = new ReadOnlySpan<string>(a);
+
+ for (int targetIndex = 0; targetIndex < length; targetIndex++)
+ {
+ Assert.Equal(1, span.Count(a[targetIndex]));
+ }
+ }
+ }
+
+ [Fact]
+ public static void TestMatchCount_RosString()
+ {
+ for (int length = 0; length < 32; length++)
+ {
+ string[] a = new string[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = (10 * (i + 1)).ToString();
+ }
+ ReadOnlySpan<string> span = new ReadOnlySpan<string>(a);
+
+ for (int targetIndex = 0; targetIndex < length - 1; targetIndex++)
+ {
+ Assert.Equal(1, span.Count(new string[] { a[targetIndex], a[targetIndex + 1] }));
+ }
+ }
+ }
+
+ [Fact]
+ public static void TestNoMatchCount_String()
+ {
+ var rnd = new Random(42);
+ for (int length = 0; length <= byte.MaxValue; length++)
+ {
+ string[] a = new string[length];
+ string target = rnd.Next(0, 256).ToString();
+ for (int i = 0; i < length; i++)
+ {
+ string val = (i + 1).ToString();
+ a[i] = val == target ? (target + 1) : val;
+ }
+
+ ReadOnlySpan<string> span = new ReadOnlySpan<string>(a);
+ Assert.Equal(0, span.Count(target));
+ }
+ }
+
+ [Fact]
+ public static void TestNoMatchCount_RosString()
+ {
+ var rnd = new Random(42);
+ for (int length = 0; length <= byte.MaxValue; length++)
+ {
+ string[] a = new string[length];
+ ReadOnlySpan<string> target = new string[] { rnd.Next(0, 256).ToString(), "0" };
+ for (int i = 0; i < length; i++)
+ {
+ string val = (i + 1).ToString();
+ a[i] = val == target[0] ? (target[0] + 1) : val;
+ }
+
+ ReadOnlySpan<string> span = new ReadOnlySpan<string>(a);
+ Assert.Equal(0, span.Count(target));
+ }
+ }
+
+ [Fact]
+ public static void TestMultipleMatchCount_String()
+ {
+ for (int length = 2; length < 32; length++)
+ {
+ string[] a = new string[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = (10 * (i + 1)).ToString();
+ }
+
+ a[^1] = a[^2] = "5555";
+
+ ReadOnlySpan<string> span = new ReadOnlySpan<string>(a);
+ Assert.Equal(2, span.Count("5555"));
+ }
+ }
+
+ [Fact]
+ public static void TestMultipleMatchCount_RosString()
+ {
+ for (int length = 4; length < 32; length++)
+ {
+ string[] a = new string[length];
+ for (int i = 0; i < length; i++)
+ {
+ a[i] = (10 * (i + 1)).ToString();
+ }
+
+ a[0] = a[1] = a[^1] = a[^2] = "5555";
+
+ ReadOnlySpan<string> span = new ReadOnlySpan<string>(a);
+ Assert.Equal(2, span.Count(new string[] { "5555", "5555" }));
+ }
+ }
+
+ [Fact]
+ public static void TestOrdinalStringCount_String()
+ {
+ ReadOnlySpan<string> span = new string[] { "ii", "II", "ìì", "ii" };
+ Assert.Equal(2, span.Count("ii"));
+ }
+
+ [Fact]
+ public static void TestOrdinalStringCount_RosString()
+ {
+ ReadOnlySpan<string> span = new string[] { "ii", "II", "ìì", "ii", "ìì" };
+ Assert.Equal(1, span.Count(new string[] { "ii", "II" }));
+ }
+
+ [Fact]
+ public static void TestOverlapDoNotCount_RosChar()
+ {
+ ReadOnlySpan<char> span = new string('a', 10);
+ Assert.Equal(5, span.Count("aa"));
+ }
+
+ [Theory]
+ [MemberData(nameof(TestHelpers.CountNullData), MemberType = typeof(TestHelpers))]
+ public static void CountNull_String(string[] spanInput, int expected)
+ {
+ ReadOnlySpan<string> theStrings = spanInput;
+ Assert.Equal(expected, theStrings.Count((string)null));
+ }
+
+ [Theory]
+ [MemberData(nameof(TestHelpers.CountNullRosData), MemberType = typeof(TestHelpers))]
+ public static void CountNull_RosString(string[] spanInput, int expected)
+ {
+ ReadOnlySpan<string> theStrings = spanInput;
+ ReadOnlySpan<string> target = new string[] { null, "9" };
+ Assert.Equal(expected, theStrings.Count(target));
+ }
+ }
+}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Linq;
+using System.Numerics;
+using Xunit;
+
+namespace System.SpanTests
+{
+ public static partial class ReadOnlySpanTests
+ {
+ [Fact]
+ public static void ZeroLengthCount_Byte()
+ {
+ Assert.Equal(0, ReadOnlySpan<byte>.Empty.Count<byte>(0));
+ }
+
+ [Fact]
+ public static void ZeroLengthCount_RosByte()
+ {
+ for (int i = 0; i <= 2; i++)
+ {
+ Assert.Equal(0, ReadOnlySpan<byte>.Empty.Count(new byte[i]));
+ }
+ }
+
+ [Fact]
+ public static void ZeroLengthNeedleCount_RosByte()
+ {
+ var span = new ReadOnlySpan<byte>(new byte[] { 5, 5, 5, 5, 5 });
+
+ Assert.Equal(0, span.Count<byte>(ReadOnlySpan<byte>.Empty));
+ }
+
+ [Fact]
+ public static void DefaultFilledCount_Byte()
+ {
+ foreach (int length in new int[] { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 255, 256 })
+ {
+ var span = new ReadOnlySpan<byte>(new byte[length]);
+ Assert.Equal(length, span.Count((byte)0));
+ }
+ }
+
+ [Fact]
+ public static void DefaultFilledCount_RosByte()
+ {
+ foreach (int length in new int[] { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 255, 256 })
+ {
+ var span = new ReadOnlySpan<byte>(new byte[length]);
+ Assert.Equal(length / 2, span.Count(new byte[2]));
+ }
+ }
+
+ [Fact]
+ public static void TestCount_Byte()
+ {
+ foreach (int length in new int[] { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 255, 256 })
+ {
+ var span = new ReadOnlySpan<byte>(Enumerable.Range(1, length).Select(i => (byte)i).ToArray());
+
+ foreach (byte target in span)
+ {
+ Assert.Equal(1, span.Count(target));
+ }
+ }
+ }
+
+ [Fact]
+ public static void TestCount_RosByte()
+ {
+ foreach (int length in new int[] { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 255, 256 })
+ {
+ var span = new ReadOnlySpan<byte>(Enumerable.Range(1, length).Select(i => (byte)i).ToArray());
+
+ for (int targetIndex = 0; targetIndex < length - 1; targetIndex++)
+ {
+ Assert.Equal(1, span.Count(new byte[] { span[targetIndex], span[targetIndex + 1] }));
+ }
+ }
+ }
+
+ [Fact]
+ public static void TestSingleValueCount_Byte()
+ {
+ foreach (int length in new int[] { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 255, 256 })
+ {
+ var span = new ReadOnlySpan<byte>(Enumerable.Range(1, length).Select(i => (byte)i).ToArray());
+
+ foreach (byte value in span)
+ {
+ Assert.Equal(1, span.Count(new byte[] { value }));
+ }
+ }
+ }
+
+ [Fact]
+ public static void TestNotCount_Byte()
+ {
+ var rnd = new Random(42);
+ int[] lengths = new int[] { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 255, 256 };
+ foreach (int length in lengths)
+ {
+ byte[] a = new byte[length];
+ byte target = (byte)rnd.Next(0, 256);
+ for (int i = 0; i < length; i++)
+ {
+ byte val = (byte)(i + 1);
+ a[i] = val == target ? (byte)(target + 1) : val;
+ }
+
+ var span = new ReadOnlySpan<byte>(a);
+ Assert.Equal(0, span.Count(target));
+ }
+ }
+
+ [Fact]
+ public static void TestNotCount_RosByte()
+ {
+ var rnd = new Random(42);
+ int[] lengths = new int[] { 0, 1, 7, 8, 9, 15, 16, 17, 31, 32, 33, 255, 256 };
+ foreach (int length in lengths)
+ {
+ byte[] a = new byte[length];
+ byte targetVal = (byte)rnd.Next(0, 256);
+ for (int i = 0; i < length; i++)
+ {
+ byte val = (byte)(i + 1);
+ a[i] = val == targetVal ? (byte)(targetVal + 1) : val;
+ }
+
+ var span = new ReadOnlySpan<byte>(a);
+ Assert.Equal(0, span.Count(new byte[] { targetVal, 0 }));
+ }
+ }
+
+ [Fact]
+ public static void TestAlignmentNotCount_Byte()
+ {
+ byte[] array = new byte[4 * Vector<byte>.Count];
+ for (var i = 0; i < Vector<byte>.Count; i++)
+ {
+ var span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count);
+ Assert.Equal(0, span.Count((byte)'1'));
+
+ span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count - 3);
+ Assert.Equal(0, span.Count((byte)'1'));
+ }
+ }
+
+ [Fact]
+ public static void TestAlignmentNotCount_RosByte()
+ {
+ byte[] array = new byte[4 * Vector<byte>.Count];
+ for (var i = 0; i < Vector<byte>.Count; i++)
+ {
+ var span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count);
+ ReadOnlySpan<byte> target = new byte[] { 1, 0 };
+ Assert.Equal(0, span.Count(target));
+
+ span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count - 3);
+ Assert.Equal(0, span.Count(target));
+ }
+ }
+
+ [Fact]
+ public static void TestAlignmentCount_Byte()
+ {
+ byte[] array = new byte[4 * Vector<byte>.Count];
+ Array.Fill(array, (byte)5);
+ for (var i = 0; i < Vector<byte>.Count; i++)
+ {
+ var span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count);
+ Assert.Equal(span.Length, span.Count<byte>(5));
+
+ span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count - 3);
+ Assert.Equal(span.Length, span.Count<byte>(5));
+ }
+ }
+
+ [Fact]
+ public static void TestAlignmentCount_RosByte()
+ {
+ byte[] array = new byte[4 * Vector<byte>.Count];
+ Array.Fill(array, (byte)5);
+ for (var i = 0; i < Vector<byte>.Count; i++)
+ {
+ var span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count);
+ ReadOnlySpan<byte> target = new byte[] { 5, 5 };
+ Assert.Equal(span.Length / 2, span.Count<byte>(target));
+
+ span = new ReadOnlySpan<byte>(array, i, 3 * Vector<byte>.Count - 3);
+ Assert.Equal(span.Length / 2, span.Count<byte>(target));
+ }
+ }
+
+ [Fact]
+ public static void TestMultipleCount_Byte()
+ {
+ for (int length = 2; length <= byte.MaxValue; length++)
+ {
+ byte[] a = new byte[length];
+ for (int i = 0; i < length; i++)
+ {
+ byte val = (byte)(i + 1);
+ a[i] = val == 200 ? (byte)201 : val;
+ }
+
+ a[^1] = a[^2] = 200;
+
+ var span = new ReadOnlySpan<byte>(a);
+ Assert.Equal(2, span.Count<byte>(200));
+ }
+ }
+
+ [Fact]
+ public static void TestMultipleCount_RosByte()
+ {
+ for (int length = 4; length <= byte.MaxValue; length++)
+ {
+ byte[] a = new byte[length];
+ for (int i = 0; i < length; i++)
+ {
+ byte val = (byte)(i + 1);
+ a[i] = val == 200 ? (byte)201 : val;
+ }
+ a[0] = a[1] = a[^1] = a[^2] = 200;
+
+ var span = new ReadOnlySpan<byte>(a);
+ Assert.Equal(2, span.Count<byte>(new byte[] { 200, 200 }));
+ }
+ }
+
+ [Fact]
+ public static void MakeSureNoCountChecksGoOutOfRange_Byte()
+ {
+ for (int length = 0; length <= byte.MaxValue; length++)
+ {
+ byte[] a = new byte[length + 2];
+ a[0] = a[^1] = 99;
+
+ var span = new ReadOnlySpan<byte>(a, 1, length);
+ Assert.Equal(0, span.Count<byte>(99));
+ }
+ }
+
+ [Fact]
+ public static void MakeSureNoCountChecksGoOutOfRange_RosByte()
+ {
+ for (int length = 0; length <= byte.MaxValue; length++)
+ {
+ byte[] a = new byte[length + 4];
+ a[0] = a[1] = a[^1] = a[^2] = 99;
+
+ var span = new ReadOnlySpan<byte>(a, 2, length);
+ Assert.Equal(0, span.Count<byte>(new byte[] { 99, 99 }));
+ }
+ }
+
+ [Fact]
+ public static void TestOverlapDoNotCount_RosByte()
+ {
+ byte[] a = new byte[10];
+ Array.Fill<byte>(a, 6);
+
+
+ var span = new ReadOnlySpan<byte>(a);
+ Assert.Equal(5, span.Count(new byte[] { 6, 6 }));
+ }
+ }
+}
<Compile Include="ReadOnlySpan\AsSpan.cs" />
<Compile Include="ReadOnlySpan\BinarySearch.cs" />
<Compile Include="ReadOnlySpan\CopyTo.cs" />
+ <Compile Include="ReadOnlySpan\Count.byte.cs" />
+ <Compile Include="ReadOnlySpan\Count.T.cs" />
<Compile Include="ReadOnlySpan\CtorArray.cs" />
<Compile Include="ReadOnlySpan\CtorArrayIntInt.cs" />
<Compile Include="ReadOnlySpan\CtorPointerInt.cs" />
/// <summary>Creates a <see cref="ReadOnlyMemory{T}"/> with the specified values in its backing field.</summary>
public static ReadOnlyMemory<T> DangerousCreateReadOnlyMemory<T>(object obj, int offset, int length) =>
DangerousCreateMemory<T>(obj, offset, length);
-
+
public static TheoryData<string[], bool> ContainsNullData => new TheoryData<string[], bool>()
{
{ new string[] { "1", null, "2" }, true},
{ new string[] { "1", null, null }, true},
{ new string[] { null, null, null }, true},
};
+
+ public static TheoryData<string[], int> CountNullData => new TheoryData<string[], int>()
+ {
+ { new string[] { "1", null, "2" }, 1},
+ { new string[] { "1", "3", "2" }, 0},
+ { null, 0},
+ { new string[] { "1", null, null }, 2},
+ { new string[] { null, null, null }, 3},
+ };
+
+ public static TheoryData<string[], int> CountNullRosData => new TheoryData<string[], int>()
+ {
+ { new string[] { "1", null, "9", "2" }, 1},
+ { new string[] { "1", "3", "9", "2" }, 0},
+ { null, 0},
+ { new string[] { "1", null, "9", null, "9"}, 2},
+ { new string[] { null, null, "9", null, "9", "9", null, "9"}, 3},
+ };
public static TheoryData<string[], string[], bool> SequenceEqualsNullData => new TheoryData<string[], string[], bool>()
{
return (startInclusive, endExclusive);
}
+ /// <summary>Counts the number of times the specified <paramref name="value"/> occurs in the <paramref name="span"/>.</summary>
+ /// <typeparam name="T">The element type of the span.</typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value for which to search.</param>
+ /// <returns>The number of times <paramref name="value"/> was found in the <paramref name="span"/>.</returns>
+ public static int Count<T>(this Span<T> span, T value) where T : IEquatable<T>? =>
+ Count((ReadOnlySpan<T>)span, value);
+
+ /// <summary>Counts the number of times the specified <paramref name="value"/> occurs in the <paramref name="span"/>.</summary>
+ /// <typeparam name="T">The element type of the span.</typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value for which to search.</param>
+ /// <returns>The number of times <paramref name="value"/> was found in the <paramref name="span"/>.</returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Count<T>(this ReadOnlySpan<T> span, T value) where T : IEquatable<T>?
+ {
+ if (RuntimeHelpers.IsBitwiseEquatable<T>())
+ {
+ if (Unsafe.SizeOf<T>() == sizeof(byte))
+ {
+ return SpanHelpers.CountValueType(
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, byte>(ref value),
+ span.Length);
+ }
+ else if (Unsafe.SizeOf<T>() == sizeof(short))
+ {
+ return SpanHelpers.CountValueType(
+ ref Unsafe.As<T, short>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, short>(ref value),
+ span.Length);
+ }
+ else if (Unsafe.SizeOf<T>() == sizeof(int))
+ {
+ return SpanHelpers.CountValueType(
+ ref Unsafe.As<T, int>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, int>(ref value),
+ span.Length);
+ }
+ else if (Unsafe.SizeOf<T>() == sizeof(long))
+ {
+ return SpanHelpers.CountValueType(
+ ref Unsafe.As<T, long>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, long>(ref value),
+ span.Length);
+ }
+ }
+
+ return SpanHelpers.Count(
+ ref MemoryMarshal.GetReference(span),
+ value,
+ span.Length);
+ }
+
+ /// <summary>Counts the number of times the specified <paramref name="value"/> occurs in the <paramref name="span"/>.</summary>
+ /// <typeparam name="T">The element type of the span.</typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value for which to search.</param>
+ /// <returns>The number of times <paramref name="value"/> was found in the <paramref name="span"/>.</returns>
+ public static int Count<T>(this Span<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>? =>
+ Count((ReadOnlySpan<T>)span, value);
+
+ /// <summary>Counts the number of times the specified <paramref name="value"/> occurs in the <paramref name="span"/>.</summary>
+ /// <typeparam name="T">The element type of the span.</typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value for which to search.</param>
+ /// <returns>The number of times <paramref name="value"/> was found in the <paramref name="span"/>.</returns>
+ public static int Count<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> value) where T : IEquatable<T>?
+ {
+ switch (value.Length)
+ {
+ case 0:
+ return 0;
+
+ case 1:
+ return Count(span, value[0]);
+
+ default:
+ int count = 0;
+
+ int pos;
+ while ((pos = span.IndexOf(value)) >= 0)
+ {
+ span = span.Slice(pos + value.Length);
+ count++;
+ }
+
+ return count;
+ }
+ }
+
/// <summary>Writes the specified interpolated string to the character span.</summary>
/// <param name="destination">The span to which the interpolated string should be formatted.</param>
/// <param name="handler">The interpolated string.</param>
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
#pragma warning disable IDE0060 // https://github.com/dotnet/roslyn-analyzers/issues/6228
return -1;
}
+
+ public static int Count<T>(ref T current, T value, int length) where T : IEquatable<T>?
+ {
+ int count = 0;
+
+ ref T end = ref Unsafe.Add(ref current, length);
+ if (value is not null)
+ {
+ while (Unsafe.IsAddressLessThan(ref current, ref end))
+ {
+ if (value.Equals(current))
+ {
+ count++;
+ }
+
+ current = ref Unsafe.Add(ref current, 1);
+ }
+ }
+ else
+ {
+ while (Unsafe.IsAddressLessThan(ref current, ref end))
+ {
+ if (current is null)
+ {
+ count++;
+ }
+
+ current = ref Unsafe.Add(ref current, 1);
+ }
+ }
+
+ return count;
+ }
+
+ public static int CountValueType<T>(ref T current, T value, int length) where T : struct, IEquatable<T>?
+ {
+ int count = 0;
+
+ ref T end = ref Unsafe.Add(ref current, length);
+ if (Vector128.IsHardwareAccelerated && length >= Vector128<T>.Count)
+ {
+ if (Vector256.IsHardwareAccelerated && length >= Vector256<T>.Count)
+ {
+ Vector256<T> targetVector = Vector256.Create(value);
+ ref T oneVectorAwayFromEndMinus1 = ref Unsafe.Subtract(ref end, Vector256<T>.Count - 1);
+ do
+ {
+ count += BitOperations.PopCount(Vector256.Equals(Vector256.LoadUnsafe(ref current), targetVector).ExtractMostSignificantBits());
+ current = ref Unsafe.Add(ref current, Vector256<T>.Count);
+ }
+ while (Unsafe.IsAddressLessThan(ref current, ref oneVectorAwayFromEndMinus1));
+
+ if (Unsafe.IsAddressLessThan(ref current, ref Unsafe.Subtract(ref end, Vector128<T>.Count - 1)))
+ {
+ count += BitOperations.PopCount(Vector128.Equals(Vector128.LoadUnsafe(ref current), Vector128.Create(value)).ExtractMostSignificantBits());
+ current = ref Unsafe.Add(ref current, Vector128<T>.Count);
+ }
+ }
+ else
+ {
+ Vector128<T> targetVector = Vector128.Create(value);
+ ref T oneVectorAwayFromEndMinus1 = ref Unsafe.Subtract(ref end, Vector128<T>.Count - 1);
+ do
+ {
+ count += BitOperations.PopCount(Vector128.Equals(Vector128.LoadUnsafe(ref current), targetVector).ExtractMostSignificantBits());
+ current = ref Unsafe.Add(ref current, Vector128<T>.Count);
+ }
+ while (Unsafe.IsAddressLessThan(ref current, ref oneVectorAwayFromEndMinus1));
+ }
+ }
+
+ while (Unsafe.IsAddressLessThan(ref current, ref end))
+ {
+ if (current.Equals(value))
+ {
+ count++;
+ }
+
+ current = ref Unsafe.Add(ref current, 1);
+ }
+
+ return count;
+ }
}
}