|
1 | 1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | 2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | 3 |
|
| 4 | +using System.Diagnostics; |
4 | 5 | using System.Runtime.CompilerServices; |
5 | 6 | using System.Runtime.InteropServices; |
6 | 7 | using System.Runtime.Intrinsics.Arm; |
7 | 8 | using System.Runtime.Intrinsics.Wasm; |
8 | 9 | using System.Runtime.Intrinsics.X86; |
| 10 | +using System.Text; |
9 | 11 |
|
10 | 12 | namespace System.Buffers |
11 | 13 | { |
12 | | - internal sealed class AsciiCharSearchValues<TOptimizations> : SearchValues<char> |
| 14 | + internal sealed class AsciiCharSearchValues<TOptimizations, TUniqueLowNibble> : SearchValues<char> |
13 | 15 | where TOptimizations : struct, IndexOfAnyAsciiSearcher.IOptimizations |
| 16 | + where TUniqueLowNibble : struct, SearchValues.IRuntimeConst |
14 | 17 | { |
15 | 18 | private IndexOfAnyAsciiSearcher.AsciiState _state; |
16 | 19 |
|
17 | | - public AsciiCharSearchValues(ReadOnlySpan<char> values) => |
18 | | - IndexOfAnyAsciiSearcher.ComputeAsciiState(values, out _state); |
| 20 | + public AsciiCharSearchValues(ReadOnlySpan<char> values) |
| 21 | + { |
| 22 | + // Despite the name being Ascii, this type may be used with non-ASCII values on ARM. |
| 23 | + // See IndexOfAnyAsciiSearcher.CanUseUniqueLowNibbleSearch. |
| 24 | + Debug.Assert(Ascii.IsValid(values) || (AdvSimd.IsSupported && TUniqueLowNibble.Value)); |
| 25 | + |
| 26 | + if (TUniqueLowNibble.Value) |
| 27 | + { |
| 28 | + IndexOfAnyAsciiSearcher.ComputeUniqueLowNibbleState(values, out _state); |
| 29 | + } |
| 30 | + else |
| 31 | + { |
| 32 | + IndexOfAnyAsciiSearcher.ComputeAsciiState(values, out _state); |
| 33 | + } |
| 34 | + } |
19 | 35 |
|
20 | 36 | internal override char[] GetValues() => |
21 | 37 | _state.Lookup.GetCharValues(); |
22 | 38 |
|
23 | 39 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
24 | 40 | internal override bool ContainsCore(char value) => |
25 | | - _state.Lookup.Contains128(value); |
| 41 | + _state.Lookup.Contains256(value); |
26 | 42 |
|
27 | 43 | [CompExactlyDependsOn(typeof(Ssse3))] |
28 | 44 | [CompExactlyDependsOn(typeof(AdvSimd))] |
29 | 45 | [CompExactlyDependsOn(typeof(PackedSimd))] |
30 | 46 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
31 | 47 | internal override int IndexOfAny(ReadOnlySpan<char> span) => |
32 | | - IndexOfAnyAsciiSearcher.IndexOfAny<IndexOfAnyAsciiSearcher.DontNegate, TOptimizations>( |
| 48 | + IndexOfAnyAsciiSearcher.IndexOfAny<IndexOfAnyAsciiSearcher.DontNegate, TOptimizations, TUniqueLowNibble>( |
33 | 49 | ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)), span.Length, ref _state); |
34 | 50 |
|
35 | 51 | [CompExactlyDependsOn(typeof(Ssse3))] |
36 | 52 | [CompExactlyDependsOn(typeof(AdvSimd))] |
37 | 53 | [CompExactlyDependsOn(typeof(PackedSimd))] |
38 | 54 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
39 | 55 | internal override int IndexOfAnyExcept(ReadOnlySpan<char> span) => |
40 | | - IndexOfAnyAsciiSearcher.IndexOfAny<IndexOfAnyAsciiSearcher.Negate, TOptimizations>( |
| 56 | + IndexOfAnyAsciiSearcher.IndexOfAny<IndexOfAnyAsciiSearcher.Negate, TOptimizations, TUniqueLowNibble>( |
41 | 57 | ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)), span.Length, ref _state); |
42 | 58 |
|
43 | 59 | [CompExactlyDependsOn(typeof(Ssse3))] |
44 | 60 | [CompExactlyDependsOn(typeof(AdvSimd))] |
45 | 61 | [CompExactlyDependsOn(typeof(PackedSimd))] |
46 | 62 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
47 | 63 | internal override int LastIndexOfAny(ReadOnlySpan<char> span) => |
48 | | - IndexOfAnyAsciiSearcher.LastIndexOfAny<IndexOfAnyAsciiSearcher.DontNegate, TOptimizations>( |
| 64 | + IndexOfAnyAsciiSearcher.LastIndexOfAny<IndexOfAnyAsciiSearcher.DontNegate, TOptimizations, TUniqueLowNibble>( |
49 | 65 | ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)), span.Length, ref _state); |
50 | 66 |
|
51 | 67 | [CompExactlyDependsOn(typeof(Ssse3))] |
52 | 68 | [CompExactlyDependsOn(typeof(AdvSimd))] |
53 | 69 | [CompExactlyDependsOn(typeof(PackedSimd))] |
54 | 70 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
55 | 71 | internal override int LastIndexOfAnyExcept(ReadOnlySpan<char> span) => |
56 | | - IndexOfAnyAsciiSearcher.LastIndexOfAny<IndexOfAnyAsciiSearcher.Negate, TOptimizations>( |
| 72 | + IndexOfAnyAsciiSearcher.LastIndexOfAny<IndexOfAnyAsciiSearcher.Negate, TOptimizations, TUniqueLowNibble>( |
57 | 73 | ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)), span.Length, ref _state); |
58 | 74 |
|
59 | 75 | [CompExactlyDependsOn(typeof(Ssse3))] |
60 | 76 | [CompExactlyDependsOn(typeof(AdvSimd))] |
61 | 77 | [CompExactlyDependsOn(typeof(PackedSimd))] |
62 | 78 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
63 | 79 | internal override bool ContainsAny(ReadOnlySpan<char> span) => |
64 | | - IndexOfAnyAsciiSearcher.ContainsAny<IndexOfAnyAsciiSearcher.DontNegate, TOptimizations>( |
| 80 | + IndexOfAnyAsciiSearcher.ContainsAny<IndexOfAnyAsciiSearcher.DontNegate, TOptimizations, TUniqueLowNibble>( |
65 | 81 | ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)), span.Length, ref _state); |
66 | 82 |
|
67 | 83 | [CompExactlyDependsOn(typeof(Ssse3))] |
68 | 84 | [CompExactlyDependsOn(typeof(AdvSimd))] |
69 | 85 | [CompExactlyDependsOn(typeof(PackedSimd))] |
70 | 86 | [MethodImpl(MethodImplOptions.AggressiveInlining)] |
71 | 87 | internal override bool ContainsAnyExcept(ReadOnlySpan<char> span) => |
72 | | - IndexOfAnyAsciiSearcher.ContainsAny<IndexOfAnyAsciiSearcher.Negate, TOptimizations>( |
| 88 | + IndexOfAnyAsciiSearcher.ContainsAny<IndexOfAnyAsciiSearcher.Negate, TOptimizations, TUniqueLowNibble>( |
73 | 89 | ref Unsafe.As<char, short>(ref MemoryMarshal.GetReference(span)), span.Length, ref _state); |
74 | 90 | } |
75 | 91 | } |
0 commit comments