-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStringViewComparer.cs
More file actions
260 lines (218 loc) · 11.3 KB
/
StringViewComparer.cs
File metadata and controls
260 lines (218 loc) · 11.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
namespace Ramstack.Text;
/// <summary>
/// Represents a <see cref="StringView"/> comparison operation
/// that uses specific case and culture-based or ordinal comparison rules.
/// </summary>
public abstract class StringViewComparer : IEqualityComparer<StringView>, IComparer<StringView>
{
/// <summary>
/// Gets a <see cref="StringViewComparer"/> object that performs a case-sensitive ordinal string comparison.
/// </summary>
public static StringViewComparer Ordinal => OrdinalComparer.Instance;
/// <summary>
/// Gets a <see cref="StringViewComparer"/> object that performs a case-insensitive ordinal string comparison.
/// </summary>
public static StringViewComparer OrdinalIgnoreCase => OrdinalIgnoreCaseComparer.Instance;
/// <summary>
/// Gets a <see cref="StringViewComparer"/> object that performs case-insensitive string comparisons
/// using the word comparison rules of the current culture.
/// </summary>
public static StringViewComparer CurrentCulture => new CultureAwareComparer(
CultureInfo.CurrentCulture.CompareInfo, CompareOptions.None);
/// <summary>
/// Gets a <see cref="StringViewComparer"/> object that performs case-insensitive string comparisons
/// using the word comparison rules of the current culture.
/// </summary>
public static StringViewComparer CurrentCultureIgnoreCase => new CultureAwareComparer(
CultureInfo.CurrentCulture.CompareInfo, CompareOptions.IgnoreCase);
/// <summary>
/// Gets a <see cref="StringViewComparer"/> object that performs a case-sensitive string comparison
/// using the word comparison rules of the invariant culture.
/// </summary>
public static StringViewComparer InvariantCulture => CultureAwareComparer.InvariantInstance;
/// <summary>
/// Gets a <see cref="StringViewComparer"/> object that performs a case-insensitive string comparison
/// using the word comparison rules of the invariant culture.
/// </summary>
public static StringViewComparer InvariantCultureIgnoreCase => CultureAwareComparer.InvariantIgnoreCaseInstance;
/// <summary>
/// Initializes a new instance of the <see cref="StringViewComparer"/> class.
/// </summary>
private protected StringViewComparer()
{
}
/// <inheritdoc />
public abstract bool Equals(StringView x, StringView y);
/// <inheritdoc />
public abstract int Compare(StringView x, StringView y);
/// <inheritdoc />
public abstract int GetHashCode(StringView obj);
/// <summary>
/// Creates a <see cref="StringViewComparer"/> that compares <see cref="StringView"/>
/// based on the rules of a specified culture.
/// </summary>
/// <param name="culture">The culture whose linguistic rules are used for the string comparison.</param>
/// <param name="ignoreCase"><see langword="true"/> for case-insensitive comparison;
/// <see langword="false"/> for case-sensitive comparison.</param>
/// <returns>
/// A new <see cref="StringViewComparer"/> object that compares strings according
/// to the rules of the specified culture and case sensitivity.
/// </returns>
public static StringViewComparer Create(CultureInfo culture, bool ignoreCase) =>
Create(culture, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
/// <summary>
/// Creates a <see cref="StringViewComparer"/> object that compares <see cref="StringView"/>
/// based on the rules of a specified culture and comparison options.
/// </summary>
/// <param name="culture">The culture whose linguistic rules are used for the string comparison.</param>
/// <param name="options">A combination of <see cref="CompareOptions"/> values
/// that specify the comparison options.</param>
/// <returns>
/// A new <see cref="StringViewComparer"/> object that compares strings
/// according to the rules of the specified culture and options.
/// </returns>
public static StringViewComparer Create(CultureInfo culture, CompareOptions options) =>
new CultureAwareComparer(culture.CompareInfo, options);
/// <summary>
/// Creates a <see cref="StringViewComparer"/> instance from the specified <see cref="StringComparison"/> value.
/// </summary>
/// <param name="comparisonType">The <see cref="StringComparison"/> instance to convert.</param>
/// <returns>
/// A <see cref="StringViewComparer"/> instance that represents
/// the equivalent value of the specified <see cref="StringComparison"/> instance.
/// </returns>
public static StringViewComparer FromComparison(StringComparison comparisonType)
{
return comparisonType switch
{
StringComparison.CurrentCulture => CurrentCulture,
StringComparison.CurrentCultureIgnoreCase => CurrentCultureIgnoreCase,
StringComparison.InvariantCulture => InvariantCulture,
StringComparison.InvariantCultureIgnoreCase => InvariantCultureIgnoreCase,
StringComparison.Ordinal => Ordinal,
StringComparison.OrdinalIgnoreCase => OrdinalIgnoreCase,
_ => Error(comparisonType)
};
static StringViewComparer Error(StringComparison comparisonType) =>
throw new ArgumentOutOfRangeException(nameof(comparisonType), comparisonType, "The specified string comparison is not supported");
}
#region Inner type: CultureAwareComparer
/// <summary>
/// Represents a comparer that performs culture-sensitive string comparisons.
/// </summary>
/// <param name="info">An instance of <see cref="CompareInfo"/> that provides
/// culture-specific comparison information.</param>
/// <param name="options">A bitwise combination of <see cref="CompareOptions"/> values
/// that specify how the comparison should be performed.</param>
private sealed class CultureAwareComparer(CompareInfo info, CompareOptions options) : StringViewComparer
#if NET9_0_OR_GREATER
, IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>
#endif
{
/// <summary>
/// A singleton instance of the <see cref="T:CultureAwareComparer"/> class
/// for invariant case-sensitive comparison.
/// </summary>
public static readonly CultureAwareComparer InvariantInstance =
new(CultureInfo.InvariantCulture.CompareInfo, CompareOptions.None);
/// <summary>
/// A singleton instance of the <see cref="T:CultureAwareComparer"/> class
/// for invariant case-insensitive comparison.
/// </summary>
public static readonly CultureAwareComparer InvariantIgnoreCaseInstance =
new(CultureInfo.InvariantCulture.CompareInfo, CompareOptions.IgnoreCase);
/// <inheritdoc />
public override bool Equals(StringView x, StringView y) =>
info.IndexOf(x, y, options) == 0;
/// <inheritdoc />
public override int GetHashCode(StringView obj) =>
info.GetHashCode(obj, options);
/// <inheritdoc />
public override int Compare(StringView x, StringView y) =>
info.IndexOf(x, y, options);
#if NET9_0_OR_GREATER
/// <inheritdoc />
bool IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.Equals(ReadOnlySpan<char> alternate, StringView other) =>
info.IndexOf(alternate, other, options) == 0;
/// <inheritdoc />
int IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.GetHashCode(ReadOnlySpan<char> alternate) =>
info.GetHashCode(alternate, options);
/// <inheritdoc />
StringView IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.Create(ReadOnlySpan<char> alternate) =>
alternate.ToString();
#endif
}
#endregion
#region Inner type: OrdinalComparer
/// <summary>
/// Represents a <see cref="StringView"/> comparison operation
/// that performs a case-sensitive ordinal string comparison.
/// </summary>
private sealed class OrdinalComparer : StringViewComparer
#if NET9_0_OR_GREATER
, IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>
#endif
{
/// <summary>
/// A singleton instance of the <see cref="T:OrdinalComparer"/> class.
/// </summary>
public static readonly OrdinalComparer Instance = new();
/// <inheritdoc />
public override bool Equals(StringView x, StringView y) =>
StringView.Equals(x, y);
/// <inheritdoc />
public override int Compare(StringView x, StringView y) =>
StringView.CompareOrdinal(x, y);
/// <inheritdoc />
public override int GetHashCode(StringView obj) =>
obj.GetHashCode();
#if NET9_0_OR_GREATER
/// <inheritdoc />
bool IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.Equals(ReadOnlySpan<char> alternate, StringView other) =>
alternate.SequenceEqual(other);
/// <inheritdoc />
int IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.GetHashCode(ReadOnlySpan<char> alternate) =>
string.GetHashCode(alternate);
/// <inheritdoc />
StringView IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.Create(ReadOnlySpan<char> alternate) =>
alternate.ToString();
#endif
}
#endregion
#region Inner type: OrdinalIgnoreCaseComparer
/// <summary>
/// Represents a <see cref="StringView"/> comparison operation
/// that performs a case-insensitive ordinal string comparison.
/// </summary>
private sealed class OrdinalIgnoreCaseComparer : StringViewComparer
#if NET9_0_OR_GREATER
, IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>
#endif
{
/// <summary>
/// A singleton instance of the <see cref="T:OrdinalIgnoreCaseComparer"/> class.
/// </summary>
public static readonly OrdinalIgnoreCaseComparer Instance = new();
/// <inheritdoc />
public override bool Equals(StringView x, StringView y) =>
StringView.Equals(x, y, StringComparison.OrdinalIgnoreCase);
/// <inheritdoc />
public override int Compare(StringView x, StringView y) =>
StringView.Compare(x, y, StringComparison.OrdinalIgnoreCase);
/// <inheritdoc />
public override int GetHashCode(StringView obj) =>
obj.GetHashCode(StringComparison.OrdinalIgnoreCase);
#if NET9_0_OR_GREATER
/// <inheritdoc />
bool IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.Equals(ReadOnlySpan<char> alternate, StringView other) =>
alternate.Equals(other, StringComparison.OrdinalIgnoreCase);
/// <inheritdoc />
int IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.GetHashCode(ReadOnlySpan<char> alternate) =>
string.GetHashCode(alternate, StringComparison.OrdinalIgnoreCase);
/// <inheritdoc />
StringView IAlternateEqualityComparer<ReadOnlySpan<char>, StringView>.Create(ReadOnlySpan<char> alternate) =>
alternate.ToString();
#endif
}
#endregion
}