Skip to content

Commit f345a70

Browse files
authored
[OSX] HybridGlobalization implement compare native function (#85965)
Implemented CompareStringNative for OSX platforms Added changes done by @ilonatommy in #86305
1 parent 18270a3 commit f345a70

File tree

14 files changed

+345
-93
lines changed

14 files changed

+345
-93
lines changed

docs/design/features/hybrid-globalization.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,65 @@ Using `IgnoreNonSpace` for these two with `HybridGlobalization` off, also return
245245
``` C#
246246
new CultureInfo("de-DE").CompareInfo.IndexOf("strasse", "stra\u00DFe", 0, CompareOptions.IgnoreNonSpace); // 0 or -1
247247
```
248+
249+
250+
### OSX
251+
252+
For OSX platforms we are using native apis instead of ICU data.
253+
254+
**String comparison**
255+
256+
Affected public APIs:
257+
- CompareInfo.Compare,
258+
- String.Compare,
259+
- String.Equals.
260+
261+
The number of `CompareOptions` and `NSStringCompareOptions` combinations are limited. Originally supported combinations can be found [here for CompareOptions](https://learn.microsoft.com/dotnet/api/system.globalization.compareoptions) and [here for NSStringCompareOptions](https://developer.apple.com/documentation/foundation/nsstringcompareoptions).
262+
263+
- `IgnoreSymbols` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`.
264+
265+
- `IgnoreKanaType` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`.
266+
267+
- `None`:
268+
269+
`CompareOptions.None` is mapped to `NSStringCompareOptions.NSLiteralSearch`
270+
271+
There are some behaviour changes. Below are examples of such cases.
272+
273+
| **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** |
274+
|:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:|
275+
| `\u3042`| `\u30A1`| None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU |
276+
| `\u304D\u3083` きゃ | `\u30AD\u30E3` キャ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU |
277+
| `\u304D\u3083` きゃ | `\u30AD\u3083` キゃ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU |
278+
| `\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C` ばびブベぼ | `\u30D0\u30D3\u3076\u30D9\uFF8E\uFF9E` バビぶベボ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU |
279+
| `\u3060`| `\u30C0`| None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU |
280+
| `\u00C0` À | `A\u0300`| None | 1 | 0 | This is not same character for native api |
281+
282+
- `StringSort` :
283+
284+
`CompareOptions.StringSort` is mapped to `NSStringCompareOptions.NSLiteralSearch` .ICU's default is to use "StringSort", i.e. nonalphanumeric symbols come before alphanumeric. That is how works also `NSLiteralSearch`.
285+
286+
- `IgnoreCase`:
287+
288+
`CompareOptions.IgnoreCase` is mapped to `NSStringCompareOptions.NSCaseInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch`
289+
290+
There are some behaviour changes. Below are examples of such cases.
291+
292+
| **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** |
293+
|:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:|
294+
| `\u3060`| `\u30C0`| IgnoreCase | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU |
295+
| `\u00C0` À | `a\u0300`| IgnoreCase | 1 | 0 | This is related to above mentioned case under `CompareOptions.None` i.e. `\u00C0` À != À `A\u0300` |
296+
297+
- `IgnoreNonSpace`:
298+
299+
`CompareOptions.IgnoreNonSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch`
300+
301+
- `IgnoreWidth`:
302+
303+
`CompareOptions.IgnoreWidth` is mapped to `NSStringCompareOptions.NSWidthInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch`
304+
305+
- All combinations that contain below `CompareOptions` always throw `PlatformNotSupportedException`:
306+
307+
`IgnoreSymbols`,
308+
309+
`IgnoreKanaType`,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Globalization;
6+
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
8+
9+
internal static partial class Interop
10+
{
11+
internal static partial class Globalization
12+
{
13+
[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_CompareStringNative", StringMarshalling = StringMarshalling.Utf16)]
14+
internal static unsafe partial int CompareStringNative(string localeName, int lNameLen, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options);
15+
}
16+
}

src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ public static string GetDistroVersionString()
356356

357357
public static bool IsInvariantGlobalization => m_isInvariant.Value;
358358
public static bool IsHybridGlobalizationOnBrowser => m_isHybrid.Value && IsBrowser;
359+
public static bool IsHybridGlobalizationOnOSX => m_isHybrid.Value && (IsOSX || IsMacCatalyst || IsiOS || IstvOS);
359360
public static bool IsNotHybridGlobalizationOnBrowser => !IsHybridGlobalizationOnBrowser;
360361
public static bool IsNotInvariantGlobalization => !IsInvariantGlobalization;
361362
public static bool IsIcuGlobalization => ICUVersion > new Version(0, 0, 0, 0);

0 commit comments

Comments
 (0)