Skip to content

Commit

Permalink
Revert "Remove Latin1CharSearchValues (#91884)" (#92726)
Browse files Browse the repository at this point in the history
* Revert "Remove Latin1CharSearchValues (#91884)"

This reverts commit 4a09c82.

* Keep the projitems formatting
  • Loading branch information
MihaZupan authored Sep 27, 2023
1 parent c3b1ed0 commit dd8e9aa
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\RangeByteSearchValues.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\RangeCharSearchValues.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\ProbabilisticCharSearchValues.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\Latin1CharSearchValues.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\SearchValues.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\SearchValues.T.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SearchValues\SearchValuesDebugView.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ public void Set(int c)
public readonly bool Contains128(char c) =>
c < 128 && ContainsUnchecked(c);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool Contains256(char c) =>
c < 256 && ContainsUnchecked(c);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly bool Contains(byte b) =>
ContainsUnchecked(b);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace System.Buffers
{
internal sealed class Latin1CharSearchValues : SearchValues<char>
{
private readonly BitVector256 _lookup;

public Latin1CharSearchValues(ReadOnlySpan<char> values)
{
foreach (char c in values)
{
if (c > 255)
{
// The values were modified concurrent with the call to SearchValues.Create
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}

_lookup.Set(c);
}
}

internal override char[] GetValues() => _lookup.GetCharValues();

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override bool ContainsCore(char value) =>
_lookup.Contains256(value);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAny(ReadOnlySpan<char> span) =>
IndexOfAny<IndexOfAnyAsciiSearcher.DontNegate>(ref MemoryMarshal.GetReference(span), span.Length);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) =>
IndexOfAny<IndexOfAnyAsciiSearcher.Negate>(ref MemoryMarshal.GetReference(span), span.Length);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int LastIndexOfAny(ReadOnlySpan<char> span) =>
LastIndexOfAny<IndexOfAnyAsciiSearcher.DontNegate>(ref MemoryMarshal.GetReference(span), span.Length);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal override int LastIndexOfAnyExcept(ReadOnlySpan<char> span) =>
LastIndexOfAny<IndexOfAnyAsciiSearcher.Negate>(ref MemoryMarshal.GetReference(span), span.Length);

private int IndexOfAny<TNegator>(ref char searchSpace, int searchSpaceLength)
where TNegator : struct, IndexOfAnyAsciiSearcher.INegator
{
ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength);
ref char cur = ref searchSpace;

while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd))
{
char c = cur;
if (TNegator.NegateIfNeeded(_lookup.Contains256(c)))
{
return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char));
}

cur = ref Unsafe.Add(ref cur, 1);
}

return -1;
}

private int LastIndexOfAny<TNegator>(ref char searchSpace, int searchSpaceLength)
where TNegator : struct, IndexOfAnyAsciiSearcher.INegator
{
for (int i = searchSpaceLength - 1; i >= 0; i--)
{
char c = Unsafe.Add(ref searchSpace, i);
if (TNegator.NegateIfNeeded(_lookup.Contains256(c)))
{
return i;
}
}

return -1;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.Arm;
using System.Runtime.Intrinsics.Wasm;
using System.Runtime.Intrinsics.X86;

Expand Down Expand Up @@ -154,6 +155,13 @@ ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(values)),
: new ProbabilisticWithAsciiCharSearchValues<IndexOfAnyAsciiSearcher.Default>(probabilisticValues);
}

// We prefer using the ProbabilisticMap over Latin1CharSearchValues if the former is vectorized.
if (!(Sse41.IsSupported || AdvSimd.Arm64.IsSupported) && maxInclusive < 256)
{
// This will also match ASCII values when IndexOfAnyAsciiSearcher is not supported.
return new Latin1CharSearchValues(values);
}

return new ProbabilisticCharSearchValues(probabilisticValues);
}

Expand Down

0 comments on commit dd8e9aa

Please sign in to comment.