|
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.Text; |
4 | 5 | using System.Diagnostics; |
5 | 6 | using System.Threading; |
6 | 7 | using System.Runtime.InteropServices; |
@@ -196,72 +197,93 @@ internal static int CompareStringIgnoreCase(ref char strA, int lengthA, ref char |
196 | 197 | ref char charA = ref strA; |
197 | 198 | ref char charB = ref strB; |
198 | 199 |
|
199 | | - while (length != 0) |
| 200 | + int index = 0; |
| 201 | + |
| 202 | + while (index < length) |
200 | 203 | { |
201 | | - // optimize for Ascii cases |
202 | | - if (charA <= '\u00FF' || length == 1 || !char.IsHighSurrogate(charA) || !char.IsHighSurrogate(charB)) |
| 204 | + char a = charA; |
| 205 | + char b = charB; |
| 206 | + char lowSurrogateA = '\0'; |
| 207 | + |
| 208 | + if (!char.IsHighSurrogate(a) || index >= lengthA - 1 || !char.IsLowSurrogate(lowSurrogateA = Unsafe.Add(ref charA, 1))) |
203 | 209 | { |
204 | | - if (charA == charB) |
| 210 | + if (!char.IsHighSurrogate(b) || index >= lengthB - 1 || !char.IsLowSurrogate(Unsafe.Add(ref charB, 1))) |
205 | 211 | { |
206 | | - length--; |
207 | | - charA = ref Unsafe.Add(ref charA, 1); |
208 | | - charB = ref Unsafe.Add(ref charB, 1); |
209 | | - continue; |
210 | | - } |
| 212 | + // |
| 213 | + // Neither A or B are surrogates |
| 214 | + // |
211 | 215 |
|
212 | | - char aUpper = OrdinalCasing.ToUpper(charA); |
213 | | - char bUpper = OrdinalCasing.ToUpper(charB); |
| 216 | + if (b == a) |
| 217 | + { |
| 218 | + index++; |
| 219 | + charA = ref Unsafe.Add(ref charA, 1); |
| 220 | + charB = ref Unsafe.Add(ref charB, 1); |
| 221 | + continue; |
| 222 | + } |
214 | 223 |
|
215 | | - if (aUpper == bUpper) |
216 | | - { |
217 | | - length--; |
218 | | - charA = ref Unsafe.Add(ref charA, 1); |
219 | | - charB = ref Unsafe.Add(ref charB, 1); |
220 | | - continue; |
| 224 | + char aUpper = OrdinalCasing.ToUpper(a); |
| 225 | + char bUpper = OrdinalCasing.ToUpper(b); |
| 226 | + |
| 227 | + if (aUpper == bUpper) |
| 228 | + { |
| 229 | + index++; |
| 230 | + charA = ref Unsafe.Add(ref charA, 1); |
| 231 | + charB = ref Unsafe.Add(ref charB, 1); |
| 232 | + continue; |
| 233 | + } |
| 234 | + |
| 235 | + return a - b; |
221 | 236 | } |
222 | 237 |
|
223 | | - return aUpper - bUpper; |
| 238 | + // |
| 239 | + // charA is not surrogate and charB is valid surrogate |
| 240 | + // |
| 241 | + |
| 242 | + return -1; |
224 | 243 | } |
225 | 244 |
|
226 | | - // We come here only of we have valid high surrogates and length > 1 |
| 245 | + // |
| 246 | + // A is Surrogate |
| 247 | + // |
227 | 248 |
|
228 | | - char a = charA; |
229 | | - char b = charB; |
230 | | - |
231 | | - length--; |
232 | | - charA = ref Unsafe.Add(ref charA, 1); |
233 | | - charB = ref Unsafe.Add(ref charB, 1); |
| 249 | + char lowSurrogateB = '\0'; |
234 | 250 |
|
235 | | - if (!char.IsLowSurrogate(charA) || !char.IsLowSurrogate(charB)) |
| 251 | + if (!char.IsHighSurrogate(b) || index >= lengthB - 1 || !char.IsLowSurrogate(lowSurrogateB = Unsafe.Add(ref charB, 1))) |
236 | 252 | { |
237 | | - // malformed Surrogates - should be rare cases |
238 | | - if (a != b) |
239 | | - { |
240 | | - return a - b; |
241 | | - } |
| 253 | + // |
| 254 | + // charB is not surrogate and charA is surrogate |
| 255 | + // |
242 | 256 |
|
243 | | - // Should be pointing to the right characters in the string to resume at. |
244 | | - // Just in case we could be pointing at high surrogate now. |
245 | | - continue; |
| 257 | + return 1; |
246 | 258 | } |
247 | 259 |
|
248 | | - // we come here only if we have valid full surrogates |
249 | | - SurrogateCasing.ToUpper(a, charA, out char h1, out char l1); |
250 | | - SurrogateCasing.ToUpper(b, charB, out char h2, out char l2); |
| 260 | + // |
| 261 | + // charA and charB are surrogates |
| 262 | + // |
| 263 | + |
| 264 | + Debug.Assert(lowSurrogateA != '\0'); |
| 265 | + Debug.Assert(lowSurrogateB != '\0'); |
251 | 266 |
|
252 | | - if (h1 != h2) |
| 267 | + if (a == b && lowSurrogateA == lowSurrogateB) |
253 | 268 | { |
254 | | - return (int)h1 - (int)h2; |
| 269 | + index += 2; |
| 270 | + charA = ref Unsafe.Add(ref charA, 2); |
| 271 | + charB = ref Unsafe.Add(ref charB, 2); |
| 272 | + continue; |
255 | 273 | } |
256 | 274 |
|
257 | | - if (l1 != l2) |
| 275 | + uint upperSurrogateA = CharUnicodeInfo.ToUpper(UnicodeUtility.GetScalarFromUtf16SurrogatePair(a, lowSurrogateA)); |
| 276 | + uint upperSurrogateB = CharUnicodeInfo.ToUpper(UnicodeUtility.GetScalarFromUtf16SurrogatePair(b, lowSurrogateB)); |
| 277 | + |
| 278 | + if (upperSurrogateA == upperSurrogateB) |
258 | 279 | { |
259 | | - return (int)l1 - (int)l2; |
| 280 | + index += 2; |
| 281 | + charA = ref Unsafe.Add(ref charA, 2); |
| 282 | + charB = ref Unsafe.Add(ref charB, 2); |
| 283 | + continue; |
260 | 284 | } |
261 | 285 |
|
262 | | - length--; |
263 | | - charA = ref Unsafe.Add(ref charA, 1); |
264 | | - charB = ref Unsafe.Add(ref charB, 1); |
| 286 | + return (int)upperSurrogateA - (int)upperSurrogateB; |
265 | 287 | } |
266 | 288 |
|
267 | 289 | return lengthA - lengthB; |
|
0 commit comments