From 5406aef0a7f075a48f85afbd09e2b71632aa02aa Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 9 May 2023 10:23:05 +0200 Subject: [PATCH 01/20] Implemented CompareStringNative --- .../src/Interop/Interop.Collation.OSX.cs | 16 ++ .../TestUtilities/System/PlatformDetection.cs | 1 + .../CompareInfo/CompareInfoTests.Compare.cs | 237 +++++++++++------- .../tests/Hybrid/Hybrid.IOS.Tests.csproj | 2 + .../System.Private.CoreLib.Shared.projitems | 4 + .../System/Globalization/CompareInfo.OSX.cs | 34 +++ .../src/System/Globalization/CompareInfo.cs | 3 + .../System.Globalization.Native/entrypoints.c | 1 + .../pal_collation.h | 9 + .../System.Globalization.Native/pal_locale.m | 126 ++++++++++ 10 files changed, 344 insertions(+), 89 deletions(-) create mode 100644 src/libraries/Common/src/Interop/Interop.Collation.OSX.cs create mode 100644 src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs diff --git a/src/libraries/Common/src/Interop/Interop.Collation.OSX.cs b/src/libraries/Common/src/Interop/Interop.Collation.OSX.cs new file mode 100644 index 00000000000000..32a7ba92cdba47 --- /dev/null +++ b/src/libraries/Common/src/Interop/Interop.Collation.OSX.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Globalization + { + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_CompareStringNative", StringMarshalling = StringMarshalling.Utf8)] + internal static unsafe partial int CompareStringNative(string localeName, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options); + } +} diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index e26bbb982ec3df..68ca7995303e7e 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -356,6 +356,7 @@ public static string GetDistroVersionString() public static bool IsInvariantGlobalization => m_isInvariant.Value; public static bool IsHybridGlobalizationOnBrowser => m_isHybrid.Value && IsBrowser; + public static bool IsHybridGlobalizationOnOSX => m_isHybrid.Value && (IsOSX || IsMacCatalyst || IsiOS || IstvOS); public static bool IsNotHybridGlobalizationOnBrowser => !IsHybridGlobalizationOnBrowser; public static bool IsNotInvariantGlobalization => !IsInvariantGlobalization; public static bool IsIcuGlobalization => ICUVersion > new Version(0, 0, 0, 0); diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index c7c24b92f80979..978abca40d9e2d 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -44,6 +44,7 @@ public static IEnumerable Compare_TestData() // PlatformDetection.IsHybridGlobalizationOnBrowser does not support IgnoreWidth CompareOptions ignoredOptions = PlatformDetection.IsHybridGlobalizationOnBrowser ? CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase : + PlatformDetection.IsHybridGlobalizationOnOSX ? CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase : CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase; yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", ignoredOptions, 0 }; @@ -108,11 +109,14 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "'", "\uFF07", ignoredOptions, 0 }; // as above yield return new object[] { s_invariantCompare, "\"", "\uFF02", ignoredOptions, 0 }; // as above - yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + } yield return new object[] { s_invariantCompare, "\u304D \u3083", "\u30AD\u3083", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u3044", "I", CompareOptions.None, 1 }; @@ -124,9 +128,12 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "ABCDE", "\uFF41\uFF42\uFF23D\uFF25", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "\u6FA4", "\u6CA2", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D0\u30D3\u3076\u30D9\uFF8E\uFF9E", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D0\u30D3\u3076\u30D9\uFF8E\uFF9E", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + } yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\uFF8E\uFF9E", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u3079\uFF8E\uFF9E", CompareOptions.None, -1 }; @@ -141,7 +148,12 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "ABCDE", "\uFF43D", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "ABCDE", "c", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u3060", "\u305F", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + } + yield return new object[] { s_invariantCompare, "\u68EE\u9D0E\u5916", "\u68EE\u9DD7\u5916", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u68EE\u9DD7\u5916", "\u68EE\u9DD7\u5916", CompareOptions.None, 0 }; @@ -171,10 +183,13 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "'", "\uFF07", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\"", "\uFF02", CompareOptions.None, -1 }; - // Hungarian - yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + // Hungarian yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + } // Turkish yield return new object[] { s_turkishCompare, "i", "I", CompareOptions.None, 1 }; @@ -191,17 +206,25 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "i", "\u0130", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "i", "\u0130", CompareOptions.IgnoreCase, -1 }; - yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, 0 }; - yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, 0 }; + } + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; - yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; - yield return new object[] { s_invariantCompare, "FooBA\u0300R", "FooB\u00C0R", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.IgnoreSymbols, 0 }; - yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; + yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.IgnoreSymbols, 0 }; + yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; + } + + yield return new object[] { s_invariantCompare, "FooBA\u0300R", "FooB\u00C0R", supportedIgnoreNonSpaceOption, 0 }; yield return new object[] { s_invariantCompare, null, "Tests", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Test's", null, CompareOptions.None, 1 }; @@ -214,22 +237,37 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "", null, CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "", "", CompareOptions.None, 0 }; - yield return new object[] { s_invariantCompare, new string('a', 5555), new string('a', 5555), CompareOptions.None, 0 }; + //if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, new string('a', 5555), new string('a', 5555), CompareOptions.None, 0 }; + } + yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreCaseIgnoreNonSpaceOptions, 0 }; yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreNonSpaceOption, -1 }; - yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnBrowser ? 1 : 0 }; - yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, -1 }; + + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, -1 }; + } + yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.None, -1 }; - yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.IgnoreSymbols, 0 }; - // some symbols e.g. currencies are not ignored correctly in HybridGlobalization - if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + + if (!PlatformDetection.IsHybridGlobalizationOnOSX) { - yield return new object[] { s_invariantCompare, "\u00A2", "\uFFE0", CompareOptions.IgnoreSymbols, 0 }; - yield return new object[] { s_invariantCompare, "$", "&", CompareOptions.IgnoreSymbols, 0 }; + yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; + + yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.IgnoreSymbols, 0 }; + // some symbols e.g. currencies are not ignored correctly in HybridGlobalization + if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + { + yield return new object[] { s_invariantCompare, "\u00A2", "\uFFE0", CompareOptions.IgnoreSymbols, 0 }; + yield return new object[] { s_invariantCompare, "$", "&", CompareOptions.IgnoreSymbols, 0 }; + } + yield return new object[] { s_invariantCompare, "\uFF65", "\u30FB", CompareOptions.IgnoreSymbols, 0 }; } - yield return new object[] { s_invariantCompare, "\uFF65", "\u30FB", CompareOptions.IgnoreSymbols, 0 }; + yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.None, -1 }; if (!PlatformDetection.IsHybridGlobalizationOnBrowser) @@ -238,19 +276,26 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.IgnoreWidth, 0 }; yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreWidth, 0 }; } - - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreSymbols, s_expectedHalfToFullFormsComparison }; - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreCase, s_expectedHalfToFullFormsComparison }; - // in HybridGlobalization on Browser IgnoreNonSpace is not supported and comparison of katakana/hiragana equivalents with supportedIgnoreNonSpaceOption gives 0 - if (!PlatformDetection.IsHybridGlobalizationOnBrowser) - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreNonSpace, s_expectedHalfToFullFormsComparison }; - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.None, s_expectedHalfToFullFormsComparison }; + + if(!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreSymbols, s_expectedHalfToFullFormsComparison }; + + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreCase, s_expectedHalfToFullFormsComparison }; + // in HybridGlobalization on Browser IgnoreNonSpace is not supported and comparison of katakana/hiragana equivalents with supportedIgnoreNonSpaceOption gives 0 + if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreNonSpace, s_expectedHalfToFullFormsComparison }; + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.None, s_expectedHalfToFullFormsComparison }; + } // in HybridGlobalization on Browser IgnoreKanaType is supported only for "ja" var kanaComparison = PlatformDetection.IsHybridGlobalizationOnBrowser ? s_japaneseCompare : s_invariantCompare; - yield return new object[] { kanaComparison, "\u3060", "\u30C0", CompareOptions.IgnoreKanaType, 0 }; - yield return new object[] { kanaComparison, "c", "C", CompareOptions.IgnoreKanaType, -1 }; - yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, s_expectedHiraganaToKatakanaCompare }; + if(!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { kanaComparison, "\u3060", "\u30C0", CompareOptions.IgnoreKanaType, 0 }; + yield return new object[] { kanaComparison, "c", "C", CompareOptions.IgnoreKanaType, -1 }; + yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, s_expectedHiraganaToKatakanaCompare }; + } // Japanese [semi-]voiced sound mark yield return new object[] { s_invariantCompare, "\u306F", "\u3070", CompareOptions.IgnoreCase, -1 }; @@ -259,12 +304,16 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", CompareOptions.IgnoreCase, -1 }; - yield return new object[] { s_invariantCompare, "\u306F", "\u3070", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u306F", "\u3071", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u3070", "\u3071", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; + + if(!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u306F", "\u3070", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u306F", "\u3071", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u3070", "\u3071", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; + } // Spanish yield return new object[] { new CultureInfo("es-ES").CompareInfo, "llegar", "lugar", CompareOptions.None, -1 }; @@ -274,6 +323,8 @@ public static IEnumerable Compare_TestData() var supportedCmpOptions = PlatformDetection.IsHybridGlobalizationOnBrowser ? CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase : + PlatformDetection.IsHybridGlobalizationOnOSX ? + CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase : CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase; yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", supportedCmpOptions, useNls ? 1: 0 }; @@ -293,16 +344,18 @@ public static IEnumerable Compare_TestData() // // Ordinal comparisons with ignore casing. // - - yield return new object[] { s_invariantCompare, "abcd", "abcd", CompareOptions.OrdinalIgnoreCase, 0}; - yield return new object[] { s_invariantCompare, "abcd", "ABCD", CompareOptions.OrdinalIgnoreCase, 0}; - yield return new object[] { s_invariantCompare, "Hello\u00F6", "HELLO\u00D6", CompareOptions.OrdinalIgnoreCase, 0}; - yield return new object[] { s_invariantCompare, "Hello\uFE6A", "Hello\U0001F601", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; - yield return new object[] { s_invariantCompare, "Hello\U0001F601", "Hello\uFE6A", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; - yield return new object[] { s_invariantCompare, "\uDBFF", "\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; - yield return new object[] { s_invariantCompare, "\uD800\uDC00", "\uDBFF", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; - yield return new object[] { s_invariantCompare, "abcdefg\uDBFF", "abcdefg\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; - yield return new object[] { s_invariantCompare, "\U00010400", "\U00010428", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 0}; + if(!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "abcd", "abcd", CompareOptions.OrdinalIgnoreCase, 0}; + yield return new object[] { s_invariantCompare, "abcd", "ABCD", CompareOptions.OrdinalIgnoreCase, 0}; + yield return new object[] { s_invariantCompare, "Hello\u00F6", "HELLO\u00D6", CompareOptions.OrdinalIgnoreCase, 0}; + yield return new object[] { s_invariantCompare, "Hello\uFE6A", "Hello\U0001F601", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; + yield return new object[] { s_invariantCompare, "Hello\U0001F601", "Hello\uFE6A", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; + yield return new object[] { s_invariantCompare, "\uDBFF", "\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; + yield return new object[] { s_invariantCompare, "\uD800\uDC00", "\uDBFF", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; + yield return new object[] { s_invariantCompare, "abcdefg\uDBFF", "abcdefg\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; + yield return new object[] { s_invariantCompare, "\U00010400", "\U00010428", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 0}; + } } [Fact] @@ -314,6 +367,7 @@ public void CompareWithUnassignedChars() } [ConditionalTheory(nameof(IsNotWindowsKanaRegressedVersion))] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS | TestPlatforms.OSX, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] [MemberData(nameof(Compare_Kana_TestData))] public void CompareWithKana(CompareInfo compareInfo, string string1, string string2, CompareOptions options, int expected) { @@ -338,40 +392,43 @@ public static IEnumerable Compare_Advanced_TestData() yield return new object[] { s_invariantCompare, "Hello", 2, 2, "elmo", 1, 2, CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Hello", 1, 0, "Goodbye", 1, 0, CompareOptions.None, 0 }; yield return new object[] { s_invariantCompare, "Hello", 5, 0, "Goodbye", 0, 0, CompareOptions.None, 0 }; - - yield return new object[] { s_invariantCompare, "Hello", 1, 2, "hElLo", 1, 2, CompareOptions.OrdinalIgnoreCase, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 1, 2, "heLLo", 1, 3, CompareOptions.OrdinalIgnoreCase, -1 }; - - yield return new object[] { s_invariantCompare, null, 0, 0, null, 0, 0, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, null, 0, 0, CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, null, 0, 0, "Hello", 0, 5, CompareOptions.Ordinal, -1 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 0, "Hello", 0, 0, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello", 0, 5, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 3, "Hello", 0, 3, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 2, 3, "Hello", 2, 3, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "He" + SoftHyphen + "llo", 0, 5, CompareOptions.Ordinal, -1 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "-==-", 3, 5, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "\uD83D\uDD53Hello\uD83D\uDD50", 1, 7, "\uD83D\uDD53Hello\uD83D\uDD54", 1, 7, CompareOptions.Ordinal, 0 }; // Surrogate split - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello123", 0, 8, CompareOptions.Ordinal, -1 }; - yield return new object[] { s_invariantCompare, "Hello123", 0, 8, "Hello", 0, 5, CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, "---aaaaaaaaaaa", 3, 11, "+++aaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, 0 }; // Equal long alignment 2, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 3, 11, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Equal long alignment 2, different compare at n=1 - yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Equal long alignment 6, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "axaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, -1 }; // Equal long alignment 6, different compare at n=1 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "aaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, 0 }; // Equal long alignment 4, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "xaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=1 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "axaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=2 - yield return new object[] { s_invariantCompare, "--aaaaaaaaaaaa", 2, 12, "++aaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, 0 }; // Equal long alignment 0, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaxaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=1 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaxaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=2 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaxaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=3 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaxaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=4 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaaxaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=5 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Different int alignment, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "aaaaaaaaaaaaax", 1, 13, CompareOptions.Ordinal, -1 }; // Different int alignment - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Different long alignment, abs of 4, one of them is 2, different at n=1 - yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 10, "++++aaaaaaaaaa", 4, 10, CompareOptions.Ordinal, 0 }; // Different long alignment, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 10, "aaaaaaaaaaaaax", 4, 10, CompareOptions.Ordinal, -1 }; // Different long alignment + + if(!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "Hello", 1, 2, "hElLo", 1, 2, CompareOptions.OrdinalIgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 1, 2, "heLLo", 1, 3, CompareOptions.OrdinalIgnoreCase, -1 }; + + yield return new object[] { s_invariantCompare, null, 0, 0, null, 0, 0, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, null, 0, 0, CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, null, 0, 0, "Hello", 0, 5, CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 0, "Hello", 0, 0, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello", 0, 5, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 3, "Hello", 0, 3, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 2, 3, "Hello", 2, 3, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "He" + SoftHyphen + "llo", 0, 5, CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "-==-", 3, 5, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "\uD83D\uDD53Hello\uD83D\uDD50", 1, 7, "\uD83D\uDD53Hello\uD83D\uDD54", 1, 7, CompareOptions.Ordinal, 0 }; // Surrogate split + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello123", 0, 8, CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "Hello123", 0, 8, "Hello", 0, 5, CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "---aaaaaaaaaaa", 3, 11, "+++aaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, 0 }; // Equal long alignment 2, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 3, 11, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Equal long alignment 2, different compare at n=1 + yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Equal long alignment 6, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "axaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, -1 }; // Equal long alignment 6, different compare at n=1 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "aaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, 0 }; // Equal long alignment 4, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "xaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=1 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "axaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=2 + yield return new object[] { s_invariantCompare, "--aaaaaaaaaaaa", 2, 12, "++aaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, 0 }; // Equal long alignment 0, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaxaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=1 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaxaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=2 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaxaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=3 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaxaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=4 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaaxaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=5 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Different int alignment, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "aaaaaaaaaaaaax", 1, 13, CompareOptions.Ordinal, -1 }; // Different int alignment + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Different long alignment, abs of 4, one of them is 2, different at n=1 + yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 10, "++++aaaaaaaaaa", 4, 10, CompareOptions.Ordinal, 0 }; // Different long alignment, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 10, "aaaaaaaaaaaaax", 4, 10, CompareOptions.Ordinal, -1 }; // Different long alignment + } } [Theory] @@ -499,6 +556,7 @@ public void Compare_Invalid() } [Fact] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS | TestPlatforms.OSX, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] public void TestIgnoreKanaAndWidthCases() { for (char c = '\uFF41'; c <= '\uFF5A'; c++) @@ -594,6 +652,7 @@ public static IEnumerable Compare_HiraganaAndKatakana_TestData() } [Theory] + [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS | TestPlatforms.OSX, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")] [MemberData(nameof(Compare_HiraganaAndKatakana_TestData))] public void TestHiraganaAndKatakana(CompareOptions[] optionsPositive, CompareOptions[] optionsNegative) { diff --git a/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj b/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj index b9887c1021aaf4..e476255b31dcfd 100644 --- a/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj +++ b/src/libraries/System.Globalization/tests/Hybrid/Hybrid.IOS.Tests.csproj @@ -32,5 +32,7 @@ + + diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index b27df31bb007a2..4149bcc5789537 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -328,6 +328,7 @@ + @@ -1264,6 +1265,9 @@ Common\Interop\Interop.Collation.cs + + + Common\Interop\Interop.Collation.OSX.cs Common\Interop\Interop.ICU.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs new file mode 100644 index 00000000000000..055bd04288fe50 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Buffers; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Text; + +namespace System.Globalization +{ + public partial class CompareInfo + { + private unsafe int CompareStringNative(ReadOnlySpan string1, ReadOnlySpan string2, CompareOptions options) + { + Debug.Assert(!GlobalizationMode.Invariant); + Debug.Assert(!GlobalizationMode.UseNls); + Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); + string cultureName = m_name; + + // GetReference may return nullptr if the input span is defaulted. The native layer handles + // this appropriately; no workaround is needed on the managed side. + + fixed (char* pString1 = &MemoryMarshal.GetReference(string1)) + fixed (char* pString2 = &MemoryMarshal.GetReference(string2)) + { + System.Diagnostics.Debug.Write("Collation CompareStringNative is called for culture: " + cultureName + "string1: " + string1.ToString() + "string2: " + string2.ToString() + "\n"); + var result = Interop.Globalization.CompareStringNative(cultureName, pString1, string1.Length, pString2, string2.Length, options); + System.Diagnostics.Debug.Write("Collation CompareStringNative result: " + result + "\n"); + return result; + } + } + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs index f205901e6d4ba3..ee478233d5dfba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.cs @@ -490,6 +490,9 @@ private unsafe int CompareStringCore(ReadOnlySpan string1, ReadOnlySpan #import @@ -568,6 +569,131 @@ Returns time format information (in native format, it needs to be converted to . return strdup([[dateFormatter dateFormat] UTF8String]); } +// collation functions +/* +Function: +CompareString +*/ +int32_t GlobalizationNative_CompareStringNative(const char* localeName, const char* lpStr1, int32_t cwStr1Length, + const char* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) +{ + NSLog(@"Collation GlobalizationNative_CompareStringNative non-default case - %d", (int32_t)comparisonOptions); + NSLocale *currentLocale; + if(localeName == NULL || strlen(localeName) == 0) + { + currentLocale = [NSLocale systemLocale]; + } + else + { + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + } + + NSString *firstString = [NSString stringWithCharacters: (const unichar *)lpStr1 length: cwStr1Length]; + NSString *secondString = [NSString stringWithCharacters: (const unichar *)lpStr2 length: cwStr2Length]; + NSRange string1Range = NSMakeRange(0, cwStr1Length); + NSStringCompareOptions options = 0; + NSLog(@"Collation GlobalizationNative_CompareStringNative before switch"); + switch (comparisonOptions) + { + case 0: + // 0: None + options = NSLiteralSearch; + break; + case 1: + // 1: IgnoreCase + options = NSCaseInsensitiveSearch; + break; + case 2: + // 2: IgnoreNonSpace + options = NSDiacriticInsensitiveSearch; + break; + case 3: + // 3: IgnoreNonSpace | IgnoreCase + options = NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; + break; + case 16: + // 16: IgnoreWidth + options = NSWidthInsensitiveSearch; + break; + case 17: + // 17: IgnoreWidth | IgnoreCase + options = NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; + break; + case 18: + // 18: IgnoreWidth | IgnoreNonSpace + options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; + break; + case 19: + // 19: IgnoreWidth | IgnoreNonSpace | IgnoreCase + options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; + break; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + default: + // 4: IgnoreSymbols + // 5: IgnoreSymbols | IgnoreCase + // 6: IgnoreSymbols | IgnoreNonSpace + // 7: IgnoreSymbols | IgnoreNonSpace | IgnoreCase + // 8: IgnoreKanaType + // 9: IgnoreKanaType | IgnoreCase + // 10: IgnoreKanaType | IgnoreNonSpace + // 11: IgnoreKanaType | IgnoreNonSpace | IgnoreCase + // 12: IgnoreKanaType | IgnoreSymbols + // 13: IgnoreKanaType | IgnoreCase | IgnoreSymbols + // 14: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace + // 15: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace | IgnoreCase + // 20: IgnoreWidth | IgnoreSymbols + // 21: IgnoreWidth | IgnoreSymbols | IgnoreCase + // 22: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace + // 23: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase + // 24: IgnoreKanaType | IgnoreWidth + // 25: IgnoreKanaType | IgnoreWidth | IgnoreCase + // 26: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace + // 27: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace | IgnoreCase + // 28: IgnoreKanaType | IgnoreWidth | IgnoreSymbols + // 29: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreCase + // 30: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace + // 31: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase + NSLog(@"Collation GlobalizationNative_CompareStringNative default case - %d", (int32_t)comparisonOptions); + NSComparisonResult res = [firstString compare:secondString]; + NSLog(@"Collation GlobalizationNative_CompareStringNative default case result is - %d", (int32_t)res); + return (int32_t)res; + } + + NSLog(@"Collation GlobalizationNative_CompareStringNative non-default case - %d", (int32_t)comparisonOptions); + + NSComparisonResult result = [firstString compare:secondString + options:options + range:string1Range + locale:currentLocale]; + NSLog(@"Collation GlobalizationNative_CompareStringNative non-default case - %d", (int32_t)result); + + return result == NSOrderedAscending ? -1 : result == NSOrderedDescending ? 1 : 0; +} + #endif #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) From 3494765cc6e60f21ccf4841fa0d7c0a38989a8fc Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 10 May 2023 13:58:21 +0200 Subject: [PATCH 02/20] moved compare function to collation file --- .../System/Globalization/CompareInfo.OSX.cs | 5 +- src/mono/mono/mini/CMakeLists.txt | 3 +- .../CMakeLists.txt | 2 +- .../pal_collation.m | 129 ++++++++++++++++++ .../System.Globalization.Native/pal_locale.m | 126 ----------------- 5 files changed, 133 insertions(+), 132 deletions(-) create mode 100644 src/native/libs/System.Globalization.Native/pal_collation.m diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs index 055bd04288fe50..8bac658302c942 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs @@ -24,10 +24,7 @@ private unsafe int CompareStringNative(ReadOnlySpan string1, ReadOnlySpan< fixed (char* pString1 = &MemoryMarshal.GetReference(string1)) fixed (char* pString2 = &MemoryMarshal.GetReference(string2)) { - System.Diagnostics.Debug.Write("Collation CompareStringNative is called for culture: " + cultureName + "string1: " + string1.ToString() + "string2: " + string2.ToString() + "\n"); - var result = Interop.Globalization.CompareStringNative(cultureName, pString1, string1.Length, pString2, string2.Length, options); - System.Diagnostics.Debug.Write("Collation CompareStringNative result: " + result + "\n"); - return result; + return Interop.Globalization.CompareStringNative(cultureName, pString1, string1.Length, pString2, string2.Length, options); } } } diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 49fe1b7f822c2d..8e60babe7bb83c 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -70,7 +70,8 @@ if(HAVE_SYS_ICU) if (TARGET_DARWIN) set(icu_shim_sources_base ${icu_shim_sources_base} - pal_locale.m) + pal_locale.m + pal_collation.m) endif() addprefix(icu_shim_sources "${ICU_SHIM_PATH}" "${icu_shim_sources_base}") diff --git a/src/native/libs/System.Globalization.Native/CMakeLists.txt b/src/native/libs/System.Globalization.Native/CMakeLists.txt index 37191a7123affd..2cb63a40a0a318 100644 --- a/src/native/libs/System.Globalization.Native/CMakeLists.txt +++ b/src/native/libs/System.Globalization.Native/CMakeLists.txt @@ -89,7 +89,7 @@ else() endif() if (CLR_CMAKE_TARGET_APPLE) - set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_locale.m) + set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_locale.m pal_collation.m) endif() # time zone names are filtered out of icu data for the browser and associated functionality is disabled diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m new file mode 100644 index 00000000000000..264b27fdb3a169 --- /dev/null +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -0,0 +1,129 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include "pal_locale_internal.h" +#include "pal_collation.h" + +#import + +#if defined(TARGET_OSX) || defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) + +/* +Function: +CompareString +*/ +int32_t GlobalizationNative_CompareStringNative(const char* localeName, const char* lpStr1, int32_t cwStr1Length, + const char* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) +{ + NSLocale *currentLocale; + if(localeName == NULL || strlen(localeName) == 0) + { + currentLocale = [NSLocale systemLocale]; + } + else + { + NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; + } + + NSString *firstString = [NSString stringWithCharacters: (const unichar *)lpStr1 length: cwStr1Length]; + NSString *secondString = [NSString stringWithCharacters: (const unichar *)lpStr2 length: cwStr2Length]; + NSRange string1Range = NSMakeRange(0, cwStr1Length); + NSStringCompareOptions options = 0; + switch (comparisonOptions) + { + case 0: + // 0: None + options = NSLiteralSearch; + break; + case 1: + // 1: IgnoreCase + options = NSCaseInsensitiveSearch; + break; + case 2: + // 2: IgnoreNonSpace + options = NSDiacriticInsensitiveSearch; + break; + case 3: + // 3: IgnoreNonSpace | IgnoreCase + options = NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; + break; + case 16: + // 16: IgnoreWidth + options = NSWidthInsensitiveSearch; + break; + case 17: + // 17: IgnoreWidth | IgnoreCase + options = NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; + break; + case 18: + // 18: IgnoreWidth | IgnoreNonSpace + options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; + break; + case 19: + // 19: IgnoreWidth | IgnoreNonSpace | IgnoreCase + options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; + break; + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + default: + // 4: IgnoreSymbols + // 5: IgnoreSymbols | IgnoreCase + // 6: IgnoreSymbols | IgnoreNonSpace + // 7: IgnoreSymbols | IgnoreNonSpace | IgnoreCase + // 8: IgnoreKanaType + // 9: IgnoreKanaType | IgnoreCase + // 10: IgnoreKanaType | IgnoreNonSpace + // 11: IgnoreKanaType | IgnoreNonSpace | IgnoreCase + // 12: IgnoreKanaType | IgnoreSymbols + // 13: IgnoreKanaType | IgnoreCase | IgnoreSymbols + // 14: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace + // 15: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace | IgnoreCase + // 20: IgnoreWidth | IgnoreSymbols + // 21: IgnoreWidth | IgnoreSymbols | IgnoreCase + // 22: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace + // 23: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase + // 24: IgnoreKanaType | IgnoreWidth + // 25: IgnoreKanaType | IgnoreWidth | IgnoreCase + // 26: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace + // 27: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace | IgnoreCase + // 28: IgnoreKanaType | IgnoreWidth | IgnoreSymbols + // 29: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreCase + // 30: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace + // 31: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase + return [firstString compare:secondString]; + //return (int32_t)res; + } + + return [firstString compare:secondString + options:options + range:string1Range + locale:currentLocale]; + //return (int32_t)result; +} + +#endif + diff --git a/src/native/libs/System.Globalization.Native/pal_locale.m b/src/native/libs/System.Globalization.Native/pal_locale.m index a9238e6cb74112..66b951db76125c 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.m +++ b/src/native/libs/System.Globalization.Native/pal_locale.m @@ -5,7 +5,6 @@ #include "pal_locale_internal.h" #include "pal_localeStringData.h" #include "pal_localeNumberData.h" -#include "pal_collation.h" #import #import @@ -569,131 +568,6 @@ Returns time format information (in native format, it needs to be converted to . return strdup([[dateFormatter dateFormat] UTF8String]); } -// collation functions -/* -Function: -CompareString -*/ -int32_t GlobalizationNative_CompareStringNative(const char* localeName, const char* lpStr1, int32_t cwStr1Length, - const char* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) -{ - NSLog(@"Collation GlobalizationNative_CompareStringNative non-default case - %d", (int32_t)comparisonOptions); - NSLocale *currentLocale; - if(localeName == NULL || strlen(localeName) == 0) - { - currentLocale = [NSLocale systemLocale]; - } - else - { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; - currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; - } - - NSString *firstString = [NSString stringWithCharacters: (const unichar *)lpStr1 length: cwStr1Length]; - NSString *secondString = [NSString stringWithCharacters: (const unichar *)lpStr2 length: cwStr2Length]; - NSRange string1Range = NSMakeRange(0, cwStr1Length); - NSStringCompareOptions options = 0; - NSLog(@"Collation GlobalizationNative_CompareStringNative before switch"); - switch (comparisonOptions) - { - case 0: - // 0: None - options = NSLiteralSearch; - break; - case 1: - // 1: IgnoreCase - options = NSCaseInsensitiveSearch; - break; - case 2: - // 2: IgnoreNonSpace - options = NSDiacriticInsensitiveSearch; - break; - case 3: - // 3: IgnoreNonSpace | IgnoreCase - options = NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; - break; - case 16: - // 16: IgnoreWidth - options = NSWidthInsensitiveSearch; - break; - case 17: - // 17: IgnoreWidth | IgnoreCase - options = NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; - break; - case 18: - // 18: IgnoreWidth | IgnoreNonSpace - options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; - break; - case 19: - // 19: IgnoreWidth | IgnoreNonSpace | IgnoreCase - options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; - break; - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 20: - case 21: - case 22: - case 23: - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - default: - // 4: IgnoreSymbols - // 5: IgnoreSymbols | IgnoreCase - // 6: IgnoreSymbols | IgnoreNonSpace - // 7: IgnoreSymbols | IgnoreNonSpace | IgnoreCase - // 8: IgnoreKanaType - // 9: IgnoreKanaType | IgnoreCase - // 10: IgnoreKanaType | IgnoreNonSpace - // 11: IgnoreKanaType | IgnoreNonSpace | IgnoreCase - // 12: IgnoreKanaType | IgnoreSymbols - // 13: IgnoreKanaType | IgnoreCase | IgnoreSymbols - // 14: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace - // 15: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace | IgnoreCase - // 20: IgnoreWidth | IgnoreSymbols - // 21: IgnoreWidth | IgnoreSymbols | IgnoreCase - // 22: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace - // 23: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase - // 24: IgnoreKanaType | IgnoreWidth - // 25: IgnoreKanaType | IgnoreWidth | IgnoreCase - // 26: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace - // 27: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace | IgnoreCase - // 28: IgnoreKanaType | IgnoreWidth | IgnoreSymbols - // 29: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreCase - // 30: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace - // 31: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase - NSLog(@"Collation GlobalizationNative_CompareStringNative default case - %d", (int32_t)comparisonOptions); - NSComparisonResult res = [firstString compare:secondString]; - NSLog(@"Collation GlobalizationNative_CompareStringNative default case result is - %d", (int32_t)res); - return (int32_t)res; - } - - NSLog(@"Collation GlobalizationNative_CompareStringNative non-default case - %d", (int32_t)comparisonOptions); - - NSComparisonResult result = [firstString compare:secondString - options:options - range:string1Range - locale:currentLocale]; - NSLog(@"Collation GlobalizationNative_CompareStringNative non-default case - %d", (int32_t)result); - - return result == NSOrderedAscending ? -1 : result == NSOrderedDescending ? 1 : 0; -} - #endif #if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) From a2bd6b1f764a6f437d5c02a919972a0644e6b017 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 10 May 2023 14:46:45 +0200 Subject: [PATCH 03/20] throw exception when options not supported --- .../src/System/Globalization/CompareInfo.OSX.cs | 11 +++++++++-- .../libs/System.Globalization.Native/pal_collation.m | 4 +--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs index 8bac658302c942..d1c505c37c485e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs @@ -20,12 +20,19 @@ private unsafe int CompareStringNative(ReadOnlySpan string1, ReadOnlySpan< // GetReference may return nullptr if the input span is defaulted. The native layer handles // this appropriately; no workaround is needed on the managed side. - + int result; fixed (char* pString1 = &MemoryMarshal.GetReference(string1)) fixed (char* pString2 = &MemoryMarshal.GetReference(string2)) { - return Interop.Globalization.CompareStringNative(cultureName, pString1, string1.Length, pString2, string2.Length, options); + result = Interop.Globalization.CompareStringNative(cultureName, pString1, string1.Length, pString2, string2.Length, options); } + + if (result == -2) + { + throw new ArgumentException("Passed compare options are not supported"); + } + + return result; } } } diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 264b27fdb3a169..79d3221ea6cda1 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -114,15 +114,13 @@ int32_t GlobalizationNative_CompareStringNative(const char* localeName, const ch // 29: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreCase // 30: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace // 31: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase - return [firstString compare:secondString]; - //return (int32_t)res; + return -2; } return [firstString compare:secondString options:options range:string1Range locale:currentLocale]; - //return (int32_t)result; } #endif From f84b02a92168d15ec8eebacc2e47d4c433fed337 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Mon, 15 May 2023 14:55:56 +0200 Subject: [PATCH 04/20] Ordinal cases tests shouldn't be skipped --- .../CompareInfo/CompareInfoTests.Compare.cs | 108 ++++++++---------- 1 file changed, 50 insertions(+), 58 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index 978abca40d9e2d..4d4cf3e09c1b29 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -213,13 +213,13 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; - + + yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; + yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; if (!PlatformDetection.IsHybridGlobalizationOnOSX) { - yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; - yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.IgnoreSymbols, 0 }; yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; } @@ -237,10 +237,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "", null, CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "", "", CompareOptions.None, 0 }; - //if (!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, new string('a', 5555), new string('a', 5555), CompareOptions.None, 0 }; - } + yield return new object[] { s_invariantCompare, new string('a', 5555), new string('a', 5555), CompareOptions.None, 0 }; yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreCaseIgnoreNonSpaceOptions, 0 }; yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreNonSpaceOption, -1 }; @@ -253,7 +250,7 @@ public static IEnumerable Compare_TestData() } yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.None, -1 }; - + if (!PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; @@ -344,18 +341,15 @@ public static IEnumerable Compare_TestData() // // Ordinal comparisons with ignore casing. // - if(!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "abcd", "abcd", CompareOptions.OrdinalIgnoreCase, 0}; - yield return new object[] { s_invariantCompare, "abcd", "ABCD", CompareOptions.OrdinalIgnoreCase, 0}; - yield return new object[] { s_invariantCompare, "Hello\u00F6", "HELLO\u00D6", CompareOptions.OrdinalIgnoreCase, 0}; - yield return new object[] { s_invariantCompare, "Hello\uFE6A", "Hello\U0001F601", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; - yield return new object[] { s_invariantCompare, "Hello\U0001F601", "Hello\uFE6A", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; - yield return new object[] { s_invariantCompare, "\uDBFF", "\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; - yield return new object[] { s_invariantCompare, "\uD800\uDC00", "\uDBFF", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; - yield return new object[] { s_invariantCompare, "abcdefg\uDBFF", "abcdefg\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; - yield return new object[] { s_invariantCompare, "\U00010400", "\U00010428", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 0}; - } + yield return new object[] { s_invariantCompare, "abcd", "abcd", CompareOptions.OrdinalIgnoreCase, 0}; + yield return new object[] { s_invariantCompare, "abcd", "ABCD", CompareOptions.OrdinalIgnoreCase, 0}; + yield return new object[] { s_invariantCompare, "Hello\u00F6", "HELLO\u00D6", CompareOptions.OrdinalIgnoreCase, 0}; + yield return new object[] { s_invariantCompare, "Hello\uFE6A", "Hello\U0001F601", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; + yield return new object[] { s_invariantCompare, "Hello\U0001F601", "Hello\uFE6A", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; + yield return new object[] { s_invariantCompare, "\uDBFF", "\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; + yield return new object[] { s_invariantCompare, "\uD800\uDC00", "\uDBFF", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 1}; + yield return new object[] { s_invariantCompare, "abcdefg\uDBFF", "abcdefg\uD800\uDC00", CompareOptions.OrdinalIgnoreCase, useNls ? 1 : -1}; + yield return new object[] { s_invariantCompare, "\U00010400", "\U00010428", CompareOptions.OrdinalIgnoreCase, useNls ? -1 : 0}; } [Fact] @@ -393,42 +387,40 @@ public static IEnumerable Compare_Advanced_TestData() yield return new object[] { s_invariantCompare, "Hello", 1, 0, "Goodbye", 1, 0, CompareOptions.None, 0 }; yield return new object[] { s_invariantCompare, "Hello", 5, 0, "Goodbye", 0, 0, CompareOptions.None, 0 }; - if(!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "Hello", 1, 2, "hElLo", 1, 2, CompareOptions.OrdinalIgnoreCase, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 1, 2, "heLLo", 1, 3, CompareOptions.OrdinalIgnoreCase, -1 }; - - yield return new object[] { s_invariantCompare, null, 0, 0, null, 0, 0, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, null, 0, 0, CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, null, 0, 0, "Hello", 0, 5, CompareOptions.Ordinal, -1 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 0, "Hello", 0, 0, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello", 0, 5, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 3, "Hello", 0, 3, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 2, 3, "Hello", 2, 3, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "He" + SoftHyphen + "llo", 0, 5, CompareOptions.Ordinal, -1 }; - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "-==-", 3, 5, CompareOptions.Ordinal, 0 }; - yield return new object[] { s_invariantCompare, "\uD83D\uDD53Hello\uD83D\uDD50", 1, 7, "\uD83D\uDD53Hello\uD83D\uDD54", 1, 7, CompareOptions.Ordinal, 0 }; // Surrogate split - yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello123", 0, 8, CompareOptions.Ordinal, -1 }; - yield return new object[] { s_invariantCompare, "Hello123", 0, 8, "Hello", 0, 5, CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, "---aaaaaaaaaaa", 3, 11, "+++aaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, 0 }; // Equal long alignment 2, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 3, 11, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Equal long alignment 2, different compare at n=1 - yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Equal long alignment 6, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "axaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, -1 }; // Equal long alignment 6, different compare at n=1 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "aaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, 0 }; // Equal long alignment 4, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "xaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=1 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "axaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=2 - yield return new object[] { s_invariantCompare, "--aaaaaaaaaaaa", 2, 12, "++aaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, 0 }; // Equal long alignment 0, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaxaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=1 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaxaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=2 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaxaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=3 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaxaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=4 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaaxaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=5 - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Different int alignment, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "aaaaaaaaaaaaax", 1, 13, CompareOptions.Ordinal, -1 }; // Different int alignment - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Different long alignment, abs of 4, one of them is 2, different at n=1 - yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 10, "++++aaaaaaaaaa", 4, 10, CompareOptions.Ordinal, 0 }; // Different long alignment, equal compare - yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 10, "aaaaaaaaaaaaax", 4, 10, CompareOptions.Ordinal, -1 }; // Different long alignment - } + + yield return new object[] { s_invariantCompare, "Hello", 1, 2, "hElLo", 1, 2, CompareOptions.OrdinalIgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 1, 2, "heLLo", 1, 3, CompareOptions.OrdinalIgnoreCase, -1 }; + + yield return new object[] { s_invariantCompare, null, 0, 0, null, 0, 0, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, null, 0, 0, CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, null, 0, 0, "Hello", 0, 5, CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 0, "Hello", 0, 0, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello", 0, 5, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 3, "Hello", 0, 3, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 2, 3, "Hello", 2, 3, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "He" + SoftHyphen + "llo", 0, 5, CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "-==-", 3, 5, CompareOptions.Ordinal, 0 }; + yield return new object[] { s_invariantCompare, "\uD83D\uDD53Hello\uD83D\uDD50", 1, 7, "\uD83D\uDD53Hello\uD83D\uDD54", 1, 7, CompareOptions.Ordinal, 0 }; // Surrogate split + yield return new object[] { s_invariantCompare, "Hello", 0, 5, "Hello123", 0, 8, CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "Hello123", 0, 8, "Hello", 0, 5, CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "---aaaaaaaaaaa", 3, 11, "+++aaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, 0 }; // Equal long alignment 2, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 3, 11, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Equal long alignment 2, different compare at n=1 + yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Equal long alignment 6, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "axaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, -1 }; // Equal long alignment 6, different compare at n=1 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "aaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, 0 }; // Equal long alignment 4, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "xaaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=1 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 14, "axaaaaaaaaaaaa", 0, 14, CompareOptions.Ordinal, -1 }; // Equal long alignment 4, different compare at n=2 + yield return new object[] { s_invariantCompare, "--aaaaaaaaaaaa", 2, 12, "++aaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, 0 }; // Equal long alignment 0, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaxaaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=1 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaxaaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=2 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaxaaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=3 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaxaaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=4 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 2, 12, "aaaaaaxaaaaaaa", 2, 12, CompareOptions.Ordinal, -1 }; // Equal long alignment 0, different compare at n=5 + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "+aaaaaaaaaaaaa", 1, 13, CompareOptions.Ordinal, 0 }; // Different int alignment, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 0, 13, "aaaaaaaaaaaaax", 1, 13, CompareOptions.Ordinal, -1 }; // Different int alignment + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 13, "aaaxaaaaaaaaaa", 3, 11, CompareOptions.Ordinal, -1 }; // Different long alignment, abs of 4, one of them is 2, different at n=1 + yield return new object[] { s_invariantCompare, "-aaaaaaaaaaaaa", 1, 10, "++++aaaaaaaaaa", 4, 10, CompareOptions.Ordinal, 0 }; // Different long alignment, equal compare + yield return new object[] { s_invariantCompare, "aaaaaaaaaaaaaa", 1, 10, "aaaaaaaaaaaaax", 4, 10, CompareOptions.Ordinal, -1 }; // Different long alignment } [Theory] From 28f76993f7e7a81724060dcc893aefad9cad3a6d Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 09:16:52 +0200 Subject: [PATCH 05/20] Did changes requested by review --- .../src/Interop/Interop.Collation.OSX.cs | 4 +- .../CompareInfo/CompareInfoTests.Compare.cs | 90 +++++------ .../System/Globalization/CompareInfo.OSX.cs | 20 ++- .../pal_collation.h | 1 + .../pal_collation.m | 142 ++++++------------ 5 files changed, 105 insertions(+), 152 deletions(-) diff --git a/src/libraries/Common/src/Interop/Interop.Collation.OSX.cs b/src/libraries/Common/src/Interop/Interop.Collation.OSX.cs index 32a7ba92cdba47..d9e502274a654a 100644 --- a/src/libraries/Common/src/Interop/Interop.Collation.OSX.cs +++ b/src/libraries/Common/src/Interop/Interop.Collation.OSX.cs @@ -10,7 +10,7 @@ internal static partial class Interop { internal static partial class Globalization { - [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_CompareStringNative", StringMarshalling = StringMarshalling.Utf8)] - internal static unsafe partial int CompareStringNative(string localeName, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options); + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_CompareStringNative", StringMarshalling = StringMarshalling.Utf16)] + internal static unsafe partial int CompareStringNative(string localeName, int lNameLen, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options); } } diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index 4d4cf3e09c1b29..e681b168818280 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -109,14 +109,11 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "'", "\uFF07", ignoredOptions, 0 }; // as above yield return new object[] { s_invariantCompare, "\"", "\uFF02", ignoredOptions, 0 }; // as above - if (!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - } + yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; yield return new object[] { s_invariantCompare, "\u304D \u3083", "\u30AD\u3083", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u3044", "I", CompareOptions.None, 1 }; @@ -128,12 +125,10 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "ABCDE", "\uFF41\uFF42\uFF23D\uFF25", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "\u6FA4", "\u6CA2", CompareOptions.None, 1 }; - if (!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D0\u30D3\u3076\u30D9\uFF8E\uFF9E", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - } + + yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D0\u30D3\u3076\u30D9\uFF8E\uFF9E", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\uFF8E\uFF9E", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u3079\uFF8E\uFF9E", CompareOptions.None, -1 }; @@ -148,12 +143,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "ABCDE", "\uFF43D", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "ABCDE", "c", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u3060", "\u305F", CompareOptions.None, 1 }; - - if (!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; - } - + yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; yield return new object[] { s_invariantCompare, "\u68EE\u9D0E\u5916", "\u68EE\u9DD7\u5916", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\u68EE\u9DD7\u5916", "\u68EE\u9DD7\u5916", CompareOptions.None, 0 }; @@ -185,11 +175,8 @@ public static IEnumerable Compare_TestData() // Hungarian yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.None, 1 }; - if (!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; - } + yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; // Turkish yield return new object[] { s_turkishCompare, "i", "I", CompareOptions.None, 1 }; @@ -206,11 +193,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "i", "\u0130", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "i", "\u0130", CompareOptions.IgnoreCase, -1 }; - if (!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, 0 }; - } - + yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; @@ -218,6 +201,8 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; + + // In HybridGlobalization on OSX IgnoreSymbols and StringSort are not supported if (!PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.IgnoreSymbols, 0 }; @@ -243,18 +228,14 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreNonSpaceOption, -1 }; yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnBrowser ? 1 : 0 }; - - if (!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, -1 }; - } + yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : -1 }; yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; + // In HybridGlobalization mode on OSX IgnoreSymbols is not supported if (!PlatformDetection.IsHybridGlobalizationOnOSX) { - yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.IgnoreSymbols, 0 }; // some symbols e.g. currencies are not ignored correctly in HybridGlobalization if (!PlatformDetection.IsHybridGlobalizationOnBrowser) @@ -273,27 +254,29 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.IgnoreWidth, 0 }; yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreWidth, 0 }; } - + + // In HybridGlobalization mode on OSX IgnoreSymbols is not supported if(!PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreSymbols, s_expectedHalfToFullFormsComparison }; - - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreCase, s_expectedHalfToFullFormsComparison }; - // in HybridGlobalization on Browser IgnoreNonSpace is not supported and comparison of katakana/hiragana equivalents with supportedIgnoreNonSpaceOption gives 0 - if (!PlatformDetection.IsHybridGlobalizationOnBrowser) - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreNonSpace, s_expectedHalfToFullFormsComparison }; - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.None, s_expectedHalfToFullFormsComparison }; } + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : s_expectedHalfToFullFormsComparison }; + // in HybridGlobalization on Browser IgnoreNonSpace is not supported and comparison of katakana/hiragana equivalents with supportedIgnoreNonSpaceOption gives 0 + if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreNonSpace, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : s_expectedHalfToFullFormsComparison }; + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.None, s_expectedHalfToFullFormsComparison }; + // in HybridGlobalization on Browser IgnoreKanaType is supported only for "ja" var kanaComparison = PlatformDetection.IsHybridGlobalizationOnBrowser ? s_japaneseCompare : s_invariantCompare; - if(!PlatformDetection.IsHybridGlobalizationOnOSX) + // In HybridGlobalization mode on OSX IgnoreKanaType is not supported + if (!PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { kanaComparison, "\u3060", "\u30C0", CompareOptions.IgnoreKanaType, 0 }; yield return new object[] { kanaComparison, "c", "C", CompareOptions.IgnoreKanaType, -1 }; - yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, s_expectedHiraganaToKatakanaCompare }; } + yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : s_expectedHiraganaToKatakanaCompare }; // Japanese [semi-]voiced sound mark yield return new object[] { s_invariantCompare, "\u306F", "\u3070", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u306F", "\u3071", CompareOptions.IgnoreCase, -1 }; @@ -302,15 +285,12 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", CompareOptions.IgnoreCase, -1 }; - if(!PlatformDetection.IsHybridGlobalizationOnOSX) - { - yield return new object[] { s_invariantCompare, "\u306F", "\u3070", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u306F", "\u3071", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u3070", "\u3071", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; - } + yield return new object[] { s_invariantCompare, "\u306F", "\u3070", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; + yield return new object[] { s_invariantCompare, "\u306F", "\u3071", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; + yield return new object[] { s_invariantCompare, "\u3070", "\u3071", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; + yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; + yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; // Spanish yield return new object[] { new CultureInfo("es-ES").CompareInfo, "llegar", "lugar", CompareOptions.None, -1 }; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs index d1c505c37c485e..87d3a9be3690fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs @@ -16,7 +16,8 @@ private unsafe int CompareStringNative(ReadOnlySpan string1, ReadOnlySpan< Debug.Assert(!GlobalizationMode.Invariant); Debug.Assert(!GlobalizationMode.UseNls); Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); - string cultureName = m_name; + + AssertComparisonSupported(options); // GetReference may return nullptr if the input span is defaulted. The native layer handles // this appropriately; no workaround is needed on the managed side. @@ -24,15 +25,28 @@ private unsafe int CompareStringNative(ReadOnlySpan string1, ReadOnlySpan< fixed (char* pString1 = &MemoryMarshal.GetReference(string1)) fixed (char* pString2 = &MemoryMarshal.GetReference(string2)) { - result = Interop.Globalization.CompareStringNative(cultureName, pString1, string1.Length, pString2, string2.Length, options); + result = Interop.Globalization.CompareStringNative(m_name, m_name.Length, pString1, string1.Length, pString2, string2.Length, options); } if (result == -2) { - throw new ArgumentException("Passed compare options are not supported"); + throw new PlatformNotSupportedException(GetPNSE(options)); } return result; } + + private static void AssertComparisonSupported(CompareOptions options) + { + if (CompareOptionsNotSupported(options)) + throw new PlatformNotSupportedException(GetPNSE(options)); + } + + private static bool CompareOptionsNotSupported(CompareOptions options) => + (options & CompareOptions.IgnoreSymbols) == CompareOptions.IgnoreSymbols || + (options & CompareOptions.IgnoreKanaType) == CompareOptions.IgnoreKanaType; + + private static string GetPNSE(CompareOptions options) => + SR.Format(SR.PlatformNotSupported_HybridGlobalizationWithCompareOptions, options); } } diff --git a/src/native/libs/System.Globalization.Native/pal_collation.h b/src/native/libs/System.Globalization.Native/pal_collation.h index 53bb9864905115..b38f97960d0dbe 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.h +++ b/src/native/libs/System.Globalization.Native/pal_collation.h @@ -64,6 +64,7 @@ PALEXPORT int32_t GlobalizationNative_GetSortKey(SortHandle* pSortHandle, #ifdef __APPLE__ PALEXPORT int32_t GlobalizationNative_CompareStringNative(const char* localeName, + int32_t lNameLength, const char* lpStr1, int32_t cwStr1Length, const char* lpStr2, diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 79d3221ea6cda1..c9ce220cfb1947 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -9,119 +9,77 @@ #if defined(TARGET_OSX) || defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) +// Enum that corresponds to C# CompareOptions +typedef enum +{ + None = 0, + IgnoreCase = 1, + IgnoreNonSpace = 2, + IgnoreWidth = 16, + +} CompareOptions; + +static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions(int32_t comparisonOptions) +{ + NSStringCompareOptions options = 0; + if (comparisonOptions == None) + options = NSLiteralSearch; + + else if (comparisonOptions == IgnoreCase) + options = NSCaseInsensitiveSearch; + + else if (comparisonOptions == IgnoreNonSpace) + options = NSDiacriticInsensitiveSearch; + + else if (comparisonOptions == (IgnoreNonSpace | IgnoreCase)) + options = NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; + + else if (comparisonOptions == IgnoreWidth) + options = NSWidthInsensitiveSearch; + + else if (comparisonOptions == (IgnoreWidth | IgnoreCase)) + options = NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; + + else if (comparisonOptions == (IgnoreWidth | IgnoreNonSpace)) + options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; + + else if (comparisonOptions == (IgnoreWidth | IgnoreNonSpace | IgnoreCase)) + options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; + + return options; +} + +#endif + /* Function: CompareString */ -int32_t GlobalizationNative_CompareStringNative(const char* localeName, const char* lpStr1, int32_t cwStr1Length, +int32_t GlobalizationNative_CompareStringNative(const char* localeName, int32_t lNameLength, const char* lpStr1, int32_t cwStr1Length, const char* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) { NSLocale *currentLocale; - if(localeName == NULL || strlen(localeName) == 0) + if(localeName == NULL || lNameLength == 0) { currentLocale = [NSLocale systemLocale]; } else { - NSString *locName = [NSString stringWithFormat:@"%s", localeName]; + NSString *locName = [NSString stringWithCharacters: (const unichar *)localeName length: lNameLength]; currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; } NSString *firstString = [NSString stringWithCharacters: (const unichar *)lpStr1 length: cwStr1Length]; NSString *secondString = [NSString stringWithCharacters: (const unichar *)lpStr2 length: cwStr2Length]; NSRange string1Range = NSMakeRange(0, cwStr1Length); - NSStringCompareOptions options = 0; - switch (comparisonOptions) - { - case 0: - // 0: None - options = NSLiteralSearch; - break; - case 1: - // 1: IgnoreCase - options = NSCaseInsensitiveSearch; - break; - case 2: - // 2: IgnoreNonSpace - options = NSDiacriticInsensitiveSearch; - break; - case 3: - // 3: IgnoreNonSpace | IgnoreCase - options = NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; - break; - case 16: - // 16: IgnoreWidth - options = NSWidthInsensitiveSearch; - break; - case 17: - // 17: IgnoreWidth | IgnoreCase - options = NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; - break; - case 18: - // 18: IgnoreWidth | IgnoreNonSpace - options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; - break; - case 19: - // 19: IgnoreWidth | IgnoreNonSpace | IgnoreCase - options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; - break; - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 20: - case 21: - case 22: - case 23: - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - default: - // 4: IgnoreSymbols - // 5: IgnoreSymbols | IgnoreCase - // 6: IgnoreSymbols | IgnoreNonSpace - // 7: IgnoreSymbols | IgnoreNonSpace | IgnoreCase - // 8: IgnoreKanaType - // 9: IgnoreKanaType | IgnoreCase - // 10: IgnoreKanaType | IgnoreNonSpace - // 11: IgnoreKanaType | IgnoreNonSpace | IgnoreCase - // 12: IgnoreKanaType | IgnoreSymbols - // 13: IgnoreKanaType | IgnoreCase | IgnoreSymbols - // 14: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace - // 15: IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace | IgnoreCase - // 20: IgnoreWidth | IgnoreSymbols - // 21: IgnoreWidth | IgnoreSymbols | IgnoreCase - // 22: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace - // 23: IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase - // 24: IgnoreKanaType | IgnoreWidth - // 25: IgnoreKanaType | IgnoreWidth | IgnoreCase - // 26: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace - // 27: IgnoreKanaType | IgnoreWidth | IgnoreNonSpace | IgnoreCase - // 28: IgnoreKanaType | IgnoreWidth | IgnoreSymbols - // 29: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreCase - // 30: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace - // 31: IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase - return -2; - } + NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions); + + // in case mapping is not found + if(options == 0) + return -2; return [firstString compare:secondString options:options range:string1Range locale:currentLocale]; } - -#endif - From ea9094b5367d866c222b4dfc948f852bfbb8cda1 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 09:44:11 +0200 Subject: [PATCH 06/20] Minor fixes in tests --- .../CompareInfo/CompareInfoTests.Compare.cs | 26 ++++++++----------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index e681b168818280..48cb714928904a 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -125,7 +125,6 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "ABCDE", "\uFF41\uFF42\uFF23D\uFF25", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "\u6FA4", "\u6CA2", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D0\u30D3\u3076\u30D9\uFF8E\uFF9E", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; @@ -173,9 +172,9 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "'", "\uFF07", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\"", "\uFF02", CompareOptions.None, -1 }; - // Hungarian - yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.None, 1 }; - yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + // Hungarian + yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; // Turkish @@ -194,13 +193,13 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "i", "\u0130", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : 0 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; - yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; + yield return new object[] { s_invariantCompare, "FooBA\u0300R", "FooB\u00C0R", supportedIgnoreNonSpaceOption, 0 }; // In HybridGlobalization on OSX IgnoreSymbols and StringSort are not supported if (!PlatformDetection.IsHybridGlobalizationOnOSX) @@ -209,8 +208,6 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; } - yield return new object[] { s_invariantCompare, "FooBA\u0300R", "FooB\u00C0R", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, null, "Tests", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Test's", null, CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, null, null, CompareOptions.None, 0 }; @@ -223,13 +220,11 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "", "", CompareOptions.None, 0 }; yield return new object[] { s_invariantCompare, new string('a', 5555), new string('a', 5555), CompareOptions.None, 0 }; - yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreCaseIgnoreNonSpaceOptions, 0 }; yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreNonSpaceOption, -1 }; - yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnBrowser ? 1 : 0 }; + yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnBrowser ? 1 : 0 }; yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : -1 }; - yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; @@ -269,6 +264,7 @@ public static IEnumerable Compare_TestData() // in HybridGlobalization on Browser IgnoreKanaType is supported only for "ja" var kanaComparison = PlatformDetection.IsHybridGlobalizationOnBrowser ? s_japaneseCompare : s_invariantCompare; + // In HybridGlobalization mode on OSX IgnoreKanaType is not supported if (!PlatformDetection.IsHybridGlobalizationOnOSX) { @@ -277,6 +273,7 @@ public static IEnumerable Compare_TestData() } yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : s_expectedHiraganaToKatakanaCompare }; + // Japanese [semi-]voiced sound mark yield return new object[] { s_invariantCompare, "\u306F", "\u3070", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u306F", "\u3071", CompareOptions.IgnoreCase, -1 }; @@ -284,7 +281,6 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", CompareOptions.IgnoreCase, -1 }; - yield return new object[] { s_invariantCompare, "\u306F", "\u3070", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; yield return new object[] { s_invariantCompare, "\u306F", "\u3071", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; yield return new object[] { s_invariantCompare, "\u3070", "\u3071", supportedIgnoreNonSpaceOption, 0 }; @@ -321,6 +317,7 @@ public static IEnumerable Compare_TestData() // // Ordinal comparisons with ignore casing. // + yield return new object[] { s_invariantCompare, "abcd", "abcd", CompareOptions.OrdinalIgnoreCase, 0}; yield return new object[] { s_invariantCompare, "abcd", "ABCD", CompareOptions.OrdinalIgnoreCase, 0}; yield return new object[] { s_invariantCompare, "Hello\u00F6", "HELLO\u00D6", CompareOptions.OrdinalIgnoreCase, 0}; @@ -365,8 +362,7 @@ public static IEnumerable Compare_Advanced_TestData() yield return new object[] { s_invariantCompare, "Hello", 2, 3, "Hemlo", 2, 3, CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Hello", 2, 2, "elmo", 1, 2, CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Hello", 1, 0, "Goodbye", 1, 0, CompareOptions.None, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 5, 0, "Goodbye", 0, 0, CompareOptions.None, 0 }; - + yield return new object[] { s_invariantCompare, "Hello", 5, 0, "Goodbye", 0, 0, CompareOptions.None, 0 }; yield return new object[] { s_invariantCompare, "Hello", 1, 2, "hElLo", 1, 2, CompareOptions.OrdinalIgnoreCase, 0 }; yield return new object[] { s_invariantCompare, "Hello", 1, 2, "heLLo", 1, 3, CompareOptions.OrdinalIgnoreCase, -1 }; From 461f926726ba2fb7bab3c17588466a11e9ba30f0 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 09:54:49 +0200 Subject: [PATCH 07/20] Remove whitespaces --- .../CompareInfo/CompareInfoTests.Compare.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index 48cb714928904a..b1a0e18f5e944b 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -173,8 +173,8 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\"", "\uFF02", CompareOptions.None, -1 }; // Hungarian - yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; - yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.None, 1 }; + yield return new object[] { s_hungarianCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; + yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.None, 1 }; yield return new object[] { s_invariantCompare, "dzsdzs", "ddzs", CompareOptions.Ordinal, 1 }; // Turkish @@ -195,7 +195,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; @@ -223,24 +223,23 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreCaseIgnoreNonSpaceOptions, 0 }; yield return new object[] { s_invariantCompare, "foobar", "FooB\u00C0R", supportedIgnoreNonSpaceOption, -1 }; - yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnBrowser ? 1 : 0 }; + yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnBrowser ? 1 : 0 }; yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : -1 }; yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.None, -1 }; - yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; // In HybridGlobalization mode on OSX IgnoreSymbols is not supported if (!PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.IgnoreSymbols, 0 }; + yield return new object[] { s_invariantCompare, "\uFF65", "\u30FB", CompareOptions.IgnoreSymbols, 0 }; // some symbols e.g. currencies are not ignored correctly in HybridGlobalization if (!PlatformDetection.IsHybridGlobalizationOnBrowser) { yield return new object[] { s_invariantCompare, "\u00A2", "\uFFE0", CompareOptions.IgnoreSymbols, 0 }; yield return new object[] { s_invariantCompare, "$", "&", CompareOptions.IgnoreSymbols, 0 }; } - yield return new object[] { s_invariantCompare, "\uFF65", "\u30FB", CompareOptions.IgnoreSymbols, 0 }; } - yield return new object[] { s_invariantCompare, "\u0021", "\uFF01", CompareOptions.None, -1 }; if (!PlatformDetection.IsHybridGlobalizationOnBrowser) @@ -317,7 +316,7 @@ public static IEnumerable Compare_TestData() // // Ordinal comparisons with ignore casing. // - + yield return new object[] { s_invariantCompare, "abcd", "abcd", CompareOptions.OrdinalIgnoreCase, 0}; yield return new object[] { s_invariantCompare, "abcd", "ABCD", CompareOptions.OrdinalIgnoreCase, 0}; yield return new object[] { s_invariantCompare, "Hello\u00F6", "HELLO\u00D6", CompareOptions.OrdinalIgnoreCase, 0}; @@ -362,7 +361,7 @@ public static IEnumerable Compare_Advanced_TestData() yield return new object[] { s_invariantCompare, "Hello", 2, 3, "Hemlo", 2, 3, CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Hello", 2, 2, "elmo", 1, 2, CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Hello", 1, 0, "Goodbye", 1, 0, CompareOptions.None, 0 }; - yield return new object[] { s_invariantCompare, "Hello", 5, 0, "Goodbye", 0, 0, CompareOptions.None, 0 }; + yield return new object[] { s_invariantCompare, "Hello", 5, 0, "Goodbye", 0, 0, CompareOptions.None, 0 }; yield return new object[] { s_invariantCompare, "Hello", 1, 2, "hElLo", 1, 2, CompareOptions.OrdinalIgnoreCase, 0 }; yield return new object[] { s_invariantCompare, "Hello", 1, 2, "heLLo", 1, 3, CompareOptions.OrdinalIgnoreCase, -1 }; From 3b7a33a72c019f4982d45a3636f3a7c235d9dfb3 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 11:32:23 +0200 Subject: [PATCH 08/20] Added changes done by @ilonatommy in #86305 --- .../CompareInfo/CompareInfoTests.Compare.cs | 140 +++++++++--------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index b1a0e18f5e944b..dd43abb2b81cc4 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -41,74 +41,74 @@ public static IEnumerable Compare_Kana_TestData() public static IEnumerable Compare_TestData() { + // PlatformDetection.IsHybridGlobalizationOnBrowser does not support IgnoreKanaType alone, it needs to be e.g. with IgnoreCase + CompareOptions validIgnoreKanaTypeOption = PlatformDetection.IsHybridGlobalizationOnBrowser ? + CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase : + CompareOptions.IgnoreKanaType; + // In HybridGlobalization, IgnoreKanaType is not supported on OSX + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", validIgnoreKanaTypeOption, 0 }; + yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", validIgnoreKanaTypeOption, 0 }; + yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", validIgnoreKanaTypeOption, 0 }; + yield return new object[] { s_invariantCompare, "\u304D \u3083", "\u30AD\u3083", validIgnoreKanaTypeOption, -1 }; + yield return new object[] { s_invariantCompare, "\u3044", "I", validIgnoreKanaTypeOption, 1 }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", validIgnoreKanaTypeOption, 0 }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", validIgnoreKanaTypeOption, 0 }; + yield return new object[] { s_invariantCompare, "\u3060", "\u305F", validIgnoreKanaTypeOption, 1 }; + yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", validIgnoreKanaTypeOption, 0 }; + yield return new object[] { s_invariantCompare, "\u68EE\u9D0E\u5916", "\u68EE\u9DD7\u5916", validIgnoreKanaTypeOption, -1 }; + yield return new object[] { s_invariantCompare, "\u2019", "'", validIgnoreKanaTypeOption, 1 }; + yield return new object[] { s_invariantCompare, "", "'", validIgnoreKanaTypeOption, -1 }; + yield return new object[] { s_invariantCompare, "\u30FC", "\uFF70", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase, 0 }; + // PlatformDetection.IsHybridGlobalizationOnBrowser does not support IgnoreWidth + if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + { + yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "'\u3000'", "' '", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, 0 }; + } + } + + yield return new object[] { s_invariantCompare, "\u6FA4", "\u6CA2", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\uFF8E\uFF9E", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\uFF8E\uFF9E", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u3079\uFF8E\uFF9E", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D6", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\u3071\u3074\u30D7\u307A", "\uFF8B\uFF9F\uFF8C\uFF9F", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u3070\uFF8E\uFF9E\u30D6", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C\u3079\u307C", "\u3079\uFF8E\uFF9E", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\u3070\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D6", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "ABDDE", "D", CompareOptions.None, -1 }; + yield return new object[] { s_invariantCompare, "\u2019\u2019\u2019\u2019", "''''", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u4E00", "\uFF11", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u2160", "\uFF11", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "9999\uFF1910", "1\uFF10", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "9999\uFF191010", "1\uFF10", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u30FC", "\uFF0D", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u30FC", "\u30FC", CompareOptions.None, 0 }; + yield return new object[] { s_invariantCompare, "\u30FC", "\u2015", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u30FC", "\u2010", CompareOptions.None, 1 }; + yield return new object[] { s_invariantCompare, "\u68EE\u9DD7\u5916", "\u68EE\u9DD7\u5916", CompareOptions.IgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "a", "A", CompareOptions.IgnoreCase, 0 }; // PlatformDetection.IsHybridGlobalizationOnBrowser does not support IgnoreWidth - CompareOptions ignoredOptions = PlatformDetection.IsHybridGlobalizationOnBrowser ? - CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase : - PlatformDetection.IsHybridGlobalizationOnOSX ? CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase : - CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase; - - yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", ignoredOptions, 0 }; - - yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u304D \u3083", "\u30AD\u3083", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3044", "I", ignoredOptions, 1 }; - - yield return new object[] { s_invariantCompare, "a", "A", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "a", "\uFF41", ignoredOptions, 0 }; // known exception for hg: should be -1 - yield return new object[] { s_invariantCompare, "ABCDE", "\uFF21\uFF22\uFF23\uFF24\uFF25", ignoredOptions, 0 }; // as above - yield return new object[] { s_invariantCompare, "ABCDE", "\uFF21\uFF22\uFF23D\uFF25", ignoredOptions, 0 }; // as above - yield return new object[] { s_invariantCompare, "ABCDE", "a\uFF22\uFF23D\uFF25", ignoredOptions, 0 }; // as above - yield return new object[] { s_invariantCompare, "ABCDE", "\uFF41\uFF42\uFF23D\uFF25", ignoredOptions, 0 }; // as above - - yield return new object[] { s_invariantCompare, "\u6FA4", "\u6CA2", ignoredOptions, 1 }; - - yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\uFF8E\uFF9E", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\uFF8E\uFF9E", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u3079\uFF8E\uFF9E", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3070\u3073\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D6", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3071\u3074\u30D7\u307A", "\uFF8B\uFF9F\uFF8C\uFF9F", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u3070\uFF8E\uFF9E\u30D6", ignoredOptions, 1 }; // known exception for hg: should be -1 - yield return new object[] { s_invariantCompare, "\u3070\u30DC\uFF8C\uFF9E\uFF8D\uFF9E\u307C\u3079\u307C", "\u3079\uFF8E\uFF9E", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3070\uFF8C\uFF9E\uFF8D\uFF9E\u307C", "\u30D6", ignoredOptions, -1 }; - - yield return new object[] { s_invariantCompare, "ABDDE", "D", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "ABCDE", "\uFF43D", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "ABCDE", "c", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u3060", "\u305F", ignoredOptions, 1 }; - yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", ignoredOptions, 0 }; - - yield return new object[] { s_invariantCompare, "\u30BF", "\uFF80", ignoredOptions, 0 }; // known exception for hg: should be -1 - - yield return new object[] { s_invariantCompare, "\u68EE\u9D0E\u5916", "\u68EE\u9DD7\u5916", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u68EE\u9DD7\u5916", "\u68EE\u9DD7\u5916", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u2019\u2019\u2019\u2019", "''''", ignoredOptions, 1 }; - yield return new object[] { s_invariantCompare, "\u2019", "'", ignoredOptions, 1 }; - yield return new object[] { s_invariantCompare, "", "'", ignoredOptions, -1 }; - yield return new object[] { s_invariantCompare, "\u4E00", "\uFF11", ignoredOptions, 1 }; - yield return new object[] { s_invariantCompare, "\u2160", "\uFF11", ignoredOptions, 1 }; - - yield return new object[] { s_invariantCompare, "0", "\uFF10", ignoredOptions, 0 }; // known exception for hg: should be -1 - yield return new object[] { s_invariantCompare, "10", "1\uFF10", ignoredOptions, 0 }; // as above - yield return new object[] { s_invariantCompare, "9999\uFF1910", "1\uFF10", ignoredOptions, 1 }; - yield return new object[] { s_invariantCompare, "9999\uFF191010", "1\uFF10", ignoredOptions, 1 }; - - yield return new object[] { s_invariantCompare, "'\u3000'", "' '", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\uFF1B", ";", ignoredOptions, 0 }; // known exception for hg: should be 1 - yield return new object[] { s_invariantCompare, "\uFF08", "(", ignoredOptions, 0 }; // known exception for hg: should be 1 - yield return new object[] { s_invariantCompare, "\u30FC", "\uFF70", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u30FC", "\uFF0D", ignoredOptions, 1 }; - yield return new object[] { s_invariantCompare, "\u30FC", "\u30FC", ignoredOptions, 0 }; - yield return new object[] { s_invariantCompare, "\u30FC", "\u2015", ignoredOptions, 1 }; - yield return new object[] { s_invariantCompare, "\u30FC", "\u2010", ignoredOptions, 1 }; - - yield return new object[] { s_invariantCompare, "/", "\uFF0F", ignoredOptions, 0 }; // known exception for hg: should be -1 - yield return new object[] { s_invariantCompare, "'", "\uFF07", ignoredOptions, 0 }; // as above - yield return new object[] { s_invariantCompare, "\"", "\uFF02", ignoredOptions, 0 }; // as above - + if (!PlatformDetection.IsHybridGlobalizationOnBrowser) + { + yield return new object[] { s_invariantCompare, "a", "\uFF41", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "ABCDE", "\uFF21\uFF22\uFF23\uFF24\uFF25", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "ABCDE", "\uFF21\uFF22\uFF23D\uFF25", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "ABCDE", "a\uFF22\uFF23D\uFF25", CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "ABCDE", "\uFF41\uFF42\uFF23D\uFF25", CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "ABCDE", "\uFF43D", CompareOptions.IgnoreWidth, -1 }; + yield return new object[] { s_invariantCompare, "ABCDE", "c", CompareOptions.IgnoreWidth, -1 }; + yield return new object[] { s_invariantCompare, "\u30BF", "\uFF80", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "0", "\uFF10", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "10", "1\uFF10", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "\uFF1B", ";", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "\uFF08", "(", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "/", "\uFF0F", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "'", "\uFF07", CompareOptions.IgnoreWidth, 0 }; + yield return new object[] { s_invariantCompare, "\"", "\uFF02", CompareOptions.IgnoreWidth, 0 }; + } yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.None, s_expectedHiraganaToKatakanaCompare }; @@ -293,14 +293,14 @@ public static IEnumerable Compare_TestData() // Misc differences between platforms bool useNls = PlatformDetection.IsNlsGlobalization; - var supportedCmpOptions = PlatformDetection.IsHybridGlobalizationOnBrowser ? + var japaneseCmp = PlatformDetection.IsHybridGlobalizationOnBrowser ? CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase : PlatformDetection.IsHybridGlobalizationOnOSX ? CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase : CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase; - yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", supportedCmpOptions, useNls ? 1: 0 }; - yield return new object[] { s_invariantCompare, "'\u3000'", "''", supportedCmpOptions, useNls ? 1 : -1 }; + yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", japaneseCmp, useNls ? 1: 0 }; + yield return new object[] { s_invariantCompare, "'\u3000'", "''", japaneseCmp, useNls ? 1 : -1 }; yield return new object[] { s_invariantCompare, "\u30BF", "\uFF80", CompareOptions.None, useNls ? 1 : -1 }; yield return new object[] { s_invariantCompare, "'\u3000'", "''", CompareOptions.None, useNls ? 1 : -1 }; yield return new object[] { s_invariantCompare, "\u30FC", "\uFF70", CompareOptions.None, useNls ? 0 : -1 }; From 4e4fb08fbbf256a1bcf8b1acd665a00f93893119 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 14:31:19 +0200 Subject: [PATCH 09/20] Added in docs info about compare function --- docs/design/features/hybrid-globalization.md | 115 +++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/hybrid-globalization.md index 629d68ef3cc84c..27ce7850ec6a3d 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/hybrid-globalization.md @@ -198,3 +198,118 @@ Web API does not expose locale-sensitive endsWith/startsWith function. As a work - `IgnoreSymbols` Only comparisons that do not skip character types are allowed. E.g. `IgnoreSymbols` skips symbol-chars in comparison/indexing. All `CompareOptions` combinations that include `IgnoreSymbols` throw `PlatformNotSupportedException`. + + +### OSX + +For OSX platforms we are using native apis instead of ICU data. + +**String comparison** + +Affected public APIs: +- CompareInfo.Compare, +- String.Compare, +- String.Equals. + +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). + +- `IgnoreSymbols` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`. + +- `IgnoreKanaType` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`. + +- `StringSort` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`. + +- `None`: + +`CompareOptions.None` is mapped to `NSStringCompareOptions.NSLiteralSearch` + +There are some behaviour changes + +| **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | +|:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| +| `\u3042` あ | `\u30A1` ァ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | +| `\u304D\u3083` きゃ | `\u30AD\u30E3` キャ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | +| `\u304D\u3083` きゃ | `\u30AD\u3083` キゃ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | +| `\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 | +| `\u3060` だ | `\u30C0` ダ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | +| `\u00C0` À | `A\u0300` À | None | 1 | 0 | This is not same character for native api | + + +- `IgnoreCase`: + +`CompareOptions.IgnoreCase` is mapped to `NSStringCompareOptions.NSCaseInsensitiveSearch` + +There are some behaviour changes + +| **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | +|:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| +| `\u20A9` ₩ | `\uFFE6` ₩ | IgnoreCase | 0 | -1 | | +| `\uFF66` ヲ | `\u30F2` ヲ | IgnoreCase | 0 | 1 | | +| `\u3060` だ | `\u30C0` ダ | IgnoreCase | 0 | 1 | | + +- `IgnoreNoneSpace`: + +`CompareOptions.IgnoreNoneSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch` + +There are some behaviour changes + +| **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | +|:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| +| `\uFF66` ヲ | `\u30F2` ヲ | IgnoreNoneSpace | 0 | 1 | | +| `\u306F` は | `\u3070` ば | IgnoreNoneSpace | -1 | 0 | | +| `\u306F` は | `\u3071` ぱ | IgnoreNoneSpace | -1 | 0 | | +| `\u30CF` ハ | `\u30D0` バ | IgnoreNoneSpace | -1 | 0 | | +| `\u30CF` ハ | `\u30D1` パ | IgnoreNoneSpace | -1 | 0 | | + + +- List of all `CompareOptions` combinations always throwing `PlatformNotSupportedException`: + +`IgnoreSymbols`, + +`IgnoreSymbols | IgnoreCase`, + +`IgnoreSymbols | IgnoreNonSpace`, + +`IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, + +`IgnoreKanaType`, + +`IgnoreKanaType | IgnoreCase`, + +`IgnoreKanaType | IgnoreNonSpace`, + +`IgnoreKanaType | IgnoreNonSpace | IgnoreCase`, + +`IgnoreKanaType | IgnoreSymbols`, + +`IgnoreKanaType | IgnoreCase | IgnoreSymbols`, + +`IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace`, + +`IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, + +`IgnoreWidth | IgnoreSymbols`, + +`IgnoreWidth | IgnoreSymbols | IgnoreCase`, + +`IgnoreWidth | IgnoreSymbols | IgnoreNonSpace`, + +`IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, + +`IgnoreKanaType | IgnoreWidth`, + +`IgnoreKanaType | IgnoreWidth | IgnoreCase`, + +`IgnoreKanaType | IgnoreWidth | IgnoreNonSpace`, + +`IgnoreKanaType | IgnoreWidth | IgnoreNonSpace | IgnoreCase`, + +`IgnoreKanaType | IgnoreWidth | IgnoreSymbols`, + +`IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreCase`, + +`IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace`, + +`IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, + +`StringSort` \ No newline at end of file From cf1e1c7a344ea1fa53a763d3521ab40686b01014 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 14:53:02 +0200 Subject: [PATCH 10/20] Minor change in doc --- docs/design/features/hybrid-globalization.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/hybrid-globalization.md index 27ce7850ec6a3d..fd7185c65ddcf1 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/hybrid-globalization.md @@ -223,7 +223,7 @@ The number of `CompareOptions` and `NSStringCompareOptions` combinations are lim `CompareOptions.None` is mapped to `NSStringCompareOptions.NSLiteralSearch` -There are some behaviour changes +There are some behaviour changes. Below are examples of such cases. | **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | |:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| @@ -239,7 +239,7 @@ There are some behaviour changes `CompareOptions.IgnoreCase` is mapped to `NSStringCompareOptions.NSCaseInsensitiveSearch` -There are some behaviour changes +There are some behaviour changes. Below are examples of such cases. | **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | |:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| @@ -251,7 +251,7 @@ There are some behaviour changes `CompareOptions.IgnoreNoneSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch` -There are some behaviour changes +There are some behaviour changes. Below are examples of such cases. | **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | |:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| From ff743ec0711487e7918b00eff1843a69984efe51 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 16:17:32 +0200 Subject: [PATCH 11/20] Mapped StringSort to None --- docs/design/features/hybrid-globalization.md | 5 +- .../CompareInfo/CompareInfoTests.Compare.cs | 4 +- .../pal_collation.m | 49 +++++++++---------- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/hybrid-globalization.md index fd7185c65ddcf1..96049d598a06db 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/hybrid-globalization.md @@ -217,8 +217,6 @@ The number of `CompareOptions` and `NSStringCompareOptions` combinations are lim - `IgnoreKanaType` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`. -- `StringSort` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`. - - `None`: `CompareOptions.None` is mapped to `NSStringCompareOptions.NSLiteralSearch` @@ -234,6 +232,7 @@ There are some behaviour changes. Below are examples of such cases. | `\u3060` だ | `\u30C0` ダ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | | `\u00C0` À | `A\u0300` À | None | 1 | 0 | This is not same character for native api | +- `StringSort` shares the same logic as None. - `IgnoreCase`: @@ -311,5 +310,3 @@ There are some behaviour changes. Below are examples of such cases. `IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace`, `IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, - -`StringSort` \ No newline at end of file diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index dd43abb2b81cc4..e8257f0d828b47 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -201,12 +201,12 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; yield return new object[] { s_invariantCompare, "FooBA\u0300R", "FooB\u00C0R", supportedIgnoreNonSpaceOption, 0 }; - // In HybridGlobalization on OSX IgnoreSymbols and StringSort are not supported + // In HybridGlobalization on OSX IgnoreSymbols is not supported if (!PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.IgnoreSymbols, 0 }; - yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; } + yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; yield return new object[] { s_invariantCompare, null, "Tests", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Test's", null, CompareOptions.None, 1 }; diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index c9ce220cfb1947..2fb737970dc8f4 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -16,37 +16,34 @@ IgnoreCase = 1, IgnoreNonSpace = 2, IgnoreWidth = 16, + StringSort = 536870912, } CompareOptions; static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions(int32_t comparisonOptions) { - NSStringCompareOptions options = 0; - if (comparisonOptions == None) - options = NSLiteralSearch; - - else if (comparisonOptions == IgnoreCase) - options = NSCaseInsensitiveSearch; - - else if (comparisonOptions == IgnoreNonSpace) - options = NSDiacriticInsensitiveSearch; - - else if (comparisonOptions == (IgnoreNonSpace | IgnoreCase)) - options = NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; - - else if (comparisonOptions == IgnoreWidth) - options = NSWidthInsensitiveSearch; - - else if (comparisonOptions == (IgnoreWidth | IgnoreCase)) - options = NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; - - else if (comparisonOptions == (IgnoreWidth | IgnoreNonSpace)) - options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; - - else if (comparisonOptions == (IgnoreWidth | IgnoreNonSpace | IgnoreCase)) - options = NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; - - return options; + switch(comparisonOptions) + { + case None: + case StringSort: + return NSLiteralSearch; + case IgnoreCase: + return NSCaseInsensitiveSearch; + case IgnoreNonSpace: + return NSDiacriticInsensitiveSearch; + case (IgnoreNonSpace | IgnoreCase): + return NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; + case IgnoreWidth: + return NSWidthInsensitiveSearch; + case (IgnoreWidth | IgnoreCase): + return NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; + case (IgnoreWidth | IgnoreNonSpace): + return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; + case (IgnoreWidth | IgnoreNonSpace | IgnoreCase): + return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; + default: + return 0; + } } #endif From 4c78a3b72c3c1cb11feb850642edfe17f514dc25 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 17 May 2023 17:20:56 +0200 Subject: [PATCH 12/20] fix spacing --- src/native/libs/System.Globalization.Native/pal_collation.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 2fb737970dc8f4..0a3727152270ab 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -72,7 +72,7 @@ int32_t GlobalizationNative_CompareStringNative(const char* localeName, int32_t NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions); // in case mapping is not found - if(options == 0) + if (options == 0) return -2; return [firstString compare:secondString From d558895baded307f6f2144c5bf4a51dd0ab9979a Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Thu, 18 May 2023 14:46:29 +0200 Subject: [PATCH 13/20] Minor fixes in doc --- docs/design/features/hybrid-globalization.md | 60 +++---------------- .../pal_collation.m | 8 +-- 2 files changed, 12 insertions(+), 56 deletions(-) diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/hybrid-globalization.md index 96049d598a06db..295ca465c44191 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/hybrid-globalization.md @@ -246,67 +246,23 @@ There are some behaviour changes. Below are examples of such cases. | `\uFF66` ヲ | `\u30F2` ヲ | IgnoreCase | 0 | 1 | | | `\u3060` だ | `\u30C0` ダ | IgnoreCase | 0 | 1 | | -- `IgnoreNoneSpace`: +- `IgnoreNonSpace`: -`CompareOptions.IgnoreNoneSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch` +`CompareOptions.IgnoreNonSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch` There are some behaviour changes. Below are examples of such cases. | **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | |:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| -| `\uFF66` ヲ | `\u30F2` ヲ | IgnoreNoneSpace | 0 | 1 | | -| `\u306F` は | `\u3070` ば | IgnoreNoneSpace | -1 | 0 | | -| `\u306F` は | `\u3071` ぱ | IgnoreNoneSpace | -1 | 0 | | -| `\u30CF` ハ | `\u30D0` バ | IgnoreNoneSpace | -1 | 0 | | -| `\u30CF` ハ | `\u30D1` パ | IgnoreNoneSpace | -1 | 0 | | +| `\uFF66` ヲ | `\u30F2` ヲ | IgnoreNonSpace | 0 | 1 | | +| `\u306F` は | `\u3070` ば | IgnoreNonSpace | -1 | 0 | | +| `\u306F` は | `\u3071` ぱ | IgnoreNonSpace | -1 | 0 | | +| `\u30CF` ハ | `\u30D0` バ | IgnoreNonSpace | -1 | 0 | | +| `\u30CF` ハ | `\u30D1` パ | IgnoreNonSpace | -1 | 0 | | -- List of all `CompareOptions` combinations always throwing `PlatformNotSupportedException`: +- All combinations that contain below `CompareOptions` always throw `PlatformNotSupportedException`: `IgnoreSymbols`, -`IgnoreSymbols | IgnoreCase`, - -`IgnoreSymbols | IgnoreNonSpace`, - -`IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, - `IgnoreKanaType`, - -`IgnoreKanaType | IgnoreCase`, - -`IgnoreKanaType | IgnoreNonSpace`, - -`IgnoreKanaType | IgnoreNonSpace | IgnoreCase`, - -`IgnoreKanaType | IgnoreSymbols`, - -`IgnoreKanaType | IgnoreCase | IgnoreSymbols`, - -`IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace`, - -`IgnoreKanaType | IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, - -`IgnoreWidth | IgnoreSymbols`, - -`IgnoreWidth | IgnoreSymbols | IgnoreCase`, - -`IgnoreWidth | IgnoreSymbols | IgnoreNonSpace`, - -`IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, - -`IgnoreKanaType | IgnoreWidth`, - -`IgnoreKanaType | IgnoreWidth | IgnoreCase`, - -`IgnoreKanaType | IgnoreWidth | IgnoreNonSpace`, - -`IgnoreKanaType | IgnoreWidth | IgnoreNonSpace | IgnoreCase`, - -`IgnoreKanaType | IgnoreWidth | IgnoreSymbols`, - -`IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreCase`, - -`IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace`, - -`IgnoreKanaType | IgnoreWidth | IgnoreSymbols | IgnoreNonSpace | IgnoreCase`, diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 0a3727152270ab..691092af58c84c 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -15,17 +15,17 @@ None = 0, IgnoreCase = 1, IgnoreNonSpace = 2, - IgnoreWidth = 16, - StringSort = 536870912, - + IgnoreWidth = 16, } CompareOptions; +#define CompareOptionsMask 0x1f + static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions(int32_t comparisonOptions) { + comparisonOptions &= CompareOptionsMask; switch(comparisonOptions) { case None: - case StringSort: return NSLiteralSearch; case IgnoreCase: return NSCaseInsensitiveSearch; From b683bce40e2da278dbc2d17792379fa923d684b0 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 19 May 2023 15:15:54 +0200 Subject: [PATCH 14/20] Updated IgnoreCase, IgnoreWith, IgnoreNonSpace --- docs/design/features/hybrid-globalization.md | 23 ++++-------- .../CompareInfo/CompareInfoTests.Compare.cs | 35 ++++++++++--------- .../pal_collation.m | 16 ++++----- 3 files changed, 34 insertions(+), 40 deletions(-) diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/hybrid-globalization.md index ab74297ea79c9d..1cd1872098df84 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/hybrid-globalization.md @@ -279,34 +279,25 @@ There are some behaviour changes. Below are examples of such cases. | `\u3060` だ | `\u30C0` ダ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | | `\u00C0` À | `A\u0300` À | None | 1 | 0 | This is not same character for native api | -- `StringSort` shares the same logic as None. +- `StringSort` : + +`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`. - `IgnoreCase`: -`CompareOptions.IgnoreCase` is mapped to `NSStringCompareOptions.NSCaseInsensitiveSearch` +`CompareOptions.IgnoreCase` is mapped to `NSStringCompareOptions.NSCaseInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch` There are some behaviour changes. Below are examples of such cases. | **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | |:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| -| `\u20A9` ₩ | `\uFFE6` ₩ | IgnoreCase | 0 | -1 | | -| `\uFF66` ヲ | `\u30F2` ヲ | IgnoreCase | 0 | 1 | | -| `\u3060` だ | `\u30C0` ダ | IgnoreCase | 0 | 1 | | +| `\u3060` だ | `\u30C0` ダ | IgnoreCase | 1 | -1 | | - `IgnoreNonSpace`: -`CompareOptions.IgnoreNonSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch` - -There are some behaviour changes. Below are examples of such cases. - -| **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | -|:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| -| `\uFF66` ヲ | `\u30F2` ヲ | IgnoreNonSpace | 0 | 1 | | -| `\u306F` は | `\u3070` ば | IgnoreNonSpace | -1 | 0 | | -| `\u306F` は | `\u3071` ぱ | IgnoreNonSpace | -1 | 0 | | -| `\u30CF` ハ | `\u30D0` バ | IgnoreNonSpace | -1 | 0 | | -| `\u30CF` ハ | `\u30D1` パ | IgnoreNonSpace | -1 | 0 | | +`CompareOptions.IgnoreNonSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch` +- `IgnoreWidth` is mapped to `NSStringCompareOptions.NSWidthInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch` - All combinations that contain below `CompareOptions` always throw `PlatformNotSupportedException`: diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index e8257f0d828b47..fcf51f931cc411 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -195,7 +195,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "A\u0300", "a\u0300", CompareOptions.IgnoreCase, 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; @@ -207,6 +207,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.IgnoreSymbols, 0 }; } yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; + yield return new object[] { s_invariantCompare, "-a", "a-", CompareOptions.StringSort, -1 }; yield return new object[] { s_invariantCompare, null, "Tests", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Test's", null, CompareOptions.None, 1 }; @@ -225,7 +226,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", supportedIgnoreNonSpaceOption, 0 }; yield return new object[] { s_invariantCompare, "\uFF9E", "\u3099", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnBrowser ? 1 : 0 }; - yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : -1 }; + yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u20A9", "\uFFE6", CompareOptions.None, -1 }; // In HybridGlobalization mode on OSX IgnoreSymbols is not supported @@ -255,10 +256,10 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreSymbols, s_expectedHalfToFullFormsComparison }; } - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : s_expectedHalfToFullFormsComparison }; + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreCase, s_expectedHalfToFullFormsComparison }; // in HybridGlobalization on Browser IgnoreNonSpace is not supported and comparison of katakana/hiragana equivalents with supportedIgnoreNonSpaceOption gives 0 if (!PlatformDetection.IsHybridGlobalizationOnBrowser) - yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreNonSpace, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : s_expectedHalfToFullFormsComparison }; + yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.IgnoreNonSpace, s_expectedHalfToFullFormsComparison }; yield return new object[] { s_invariantCompare, "\uFF66", "\u30F2", CompareOptions.None, s_expectedHalfToFullFormsComparison }; // in HybridGlobalization on Browser IgnoreKanaType is supported only for "ja" @@ -271,7 +272,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { kanaComparison, "c", "C", CompareOptions.IgnoreKanaType, -1 }; } - yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 0 : s_expectedHiraganaToKatakanaCompare }; + yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare }; // Japanese [semi-]voiced sound mark yield return new object[] { s_invariantCompare, "\u306F", "\u3070", CompareOptions.IgnoreCase, -1 }; @@ -280,11 +281,11 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", CompareOptions.IgnoreCase, -1 }; yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", CompareOptions.IgnoreCase, -1 }; - yield return new object[] { s_invariantCompare, "\u306F", "\u3070", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; - yield return new object[] { s_invariantCompare, "\u306F", "\u3071", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; + yield return new object[] { s_invariantCompare, "\u306F", "\u3070", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u306F", "\u3071", supportedIgnoreNonSpaceOption, 0 }; yield return new object[] { s_invariantCompare, "\u3070", "\u3071", supportedIgnoreNonSpaceOption, 0 }; - yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; - yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", supportedIgnoreNonSpaceOption, PlatformDetection.IsHybridGlobalizationOnOSX ? -1 : 0 }; + yield return new object[] { s_invariantCompare, "\u30CF", "\u30D0", supportedIgnoreNonSpaceOption, 0 }; + yield return new object[] { s_invariantCompare, "\u30CF", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; yield return new object[] { s_invariantCompare, "\u30D0", "\u30D1", supportedIgnoreNonSpaceOption, 0 }; // Spanish @@ -293,14 +294,16 @@ public static IEnumerable Compare_TestData() // Misc differences between platforms bool useNls = PlatformDetection.IsNlsGlobalization; - var japaneseCmp = PlatformDetection.IsHybridGlobalizationOnBrowser ? - CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase : - PlatformDetection.IsHybridGlobalizationOnOSX ? - CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase : - CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + var japaneseCmp = PlatformDetection.IsHybridGlobalizationOnBrowser ? + CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase : + CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase; + + yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", japaneseCmp, useNls ? 1: 0 }; + yield return new object[] { s_invariantCompare, "'\u3000'", "''", japaneseCmp, useNls ? 1 : -1 }; + } - yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", japaneseCmp, useNls ? 1: 0 }; - yield return new object[] { s_invariantCompare, "'\u3000'", "''", japaneseCmp, useNls ? 1 : -1 }; yield return new object[] { s_invariantCompare, "\u30BF", "\uFF80", CompareOptions.None, useNls ? 1 : -1 }; yield return new object[] { s_invariantCompare, "'\u3000'", "''", CompareOptions.None, useNls ? 1 : -1 }; yield return new object[] { s_invariantCompare, "\u30FC", "\uFF70", CompareOptions.None, useNls ? 0 : -1 }; diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 691092af58c84c..6ecb5e70bed423 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -15,7 +15,7 @@ None = 0, IgnoreCase = 1, IgnoreNonSpace = 2, - IgnoreWidth = 16, + IgnoreWidth = 16, } CompareOptions; #define CompareOptionsMask 0x1f @@ -28,19 +28,19 @@ static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions( case None: return NSLiteralSearch; case IgnoreCase: - return NSCaseInsensitiveSearch; + return NSCaseInsensitiveSearch | NSLiteralSearch; case IgnoreNonSpace: - return NSDiacriticInsensitiveSearch; + return NSDiacriticInsensitiveSearch | NSLiteralSearch; case (IgnoreNonSpace | IgnoreCase): - return NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch; + return NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch | NSLiteralSearch; case IgnoreWidth: - return NSWidthInsensitiveSearch; + return NSWidthInsensitiveSearch | NSLiteralSearch; case (IgnoreWidth | IgnoreCase): - return NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; + return NSWidthInsensitiveSearch | NSCaseInsensitiveSearch | NSLiteralSearch; case (IgnoreWidth | IgnoreNonSpace): - return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch; + return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSLiteralSearch; case (IgnoreWidth | IgnoreNonSpace | IgnoreCase): - return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch; + return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSLiteralSearch; default: return 0; } From 73fa470494f2915795a69c91e20748c5265e6053 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 19 May 2023 16:36:54 +0200 Subject: [PATCH 15/20] Refactored mapping function --- docs/design/features/hybrid-globalization.md | 2 +- .../pal_collation.m | 37 ++++++++----------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/hybrid-globalization.md index 1cd1872098df84..e0ed7714e0dff1 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/hybrid-globalization.md @@ -279,7 +279,7 @@ There are some behaviour changes. Below are examples of such cases. | `\u3060` だ | `\u30C0` ダ | None | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | | `\u00C0` À | `A\u0300` À | None | 1 | 0 | This is not same character for native api | -- `StringSort` : +- `StringSort` : `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`. diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 6ecb5e70bed423..74317308cd8b55 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -22,28 +22,23 @@ static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions(int32_t comparisonOptions) { + int32_t supportedOptions = IgnoreCase | IgnoreNonSpace | IgnoreWidth; + NSStringCompareOptions options = NSLiteralSearch; comparisonOptions &= CompareOptionsMask; - switch(comparisonOptions) - { - case None: - return NSLiteralSearch; - case IgnoreCase: - return NSCaseInsensitiveSearch | NSLiteralSearch; - case IgnoreNonSpace: - return NSDiacriticInsensitiveSearch | NSLiteralSearch; - case (IgnoreNonSpace | IgnoreCase): - return NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch | NSLiteralSearch; - case IgnoreWidth: - return NSWidthInsensitiveSearch | NSLiteralSearch; - case (IgnoreWidth | IgnoreCase): - return NSWidthInsensitiveSearch | NSCaseInsensitiveSearch | NSLiteralSearch; - case (IgnoreWidth | IgnoreNonSpace): - return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSLiteralSearch; - case (IgnoreWidth | IgnoreNonSpace | IgnoreCase): - return NSWidthInsensitiveSearch | NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSLiteralSearch; - default: - return 0; - } + + if ((comparisonOptions | supportedOptions) != supportedOptions) + return 0; + + if (comparisonOptions & IgnoreCase) + options |= NSCaseInsensitiveSearch; + + if (comparisonOptions & IgnoreNonSpace) + options |= NSDiacriticInsensitiveSearch; + + if (comparisonOptions & IgnoreWidth) + options |= NSWidthInsensitiveSearch; + + return options; } #endif From 4ce304a3f8366199f01f7385702eff37fc1fa156 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 19 May 2023 16:56:06 +0200 Subject: [PATCH 16/20] Minor changes in docs and test cases --- docs/design/features/hybrid-globalization.md | 7 +++++-- .../tests/CompareInfo/CompareInfoTests.Compare.cs | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/hybrid-globalization.md index e0ed7714e0dff1..916bada554ebaa 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/hybrid-globalization.md @@ -291,13 +291,16 @@ There are some behaviour changes. Below are examples of such cases. | **character 1** | **character 2** | **CompareOptions** | **hybrid globalization** | **icu** | **comments** | |:---------------:|:---------------:|--------------------|:------------------------:|:-------:|:-------------------------------------------------------:| -| `\u3060` だ | `\u30C0` ダ | IgnoreCase | 1 | -1 | | +| `\u3060` だ | `\u30C0` ダ | IgnoreCase | 1 | -1 | hiragana and katakana characters are ordered differently compared to ICU | +| `\u00C0` À | `a\u0300` à | IgnoreCase | 1 | 0 | This is related to above mentioned case under `CompareOptions.None` i.e. `\u00C0` À != À `A\u0300` | - `IgnoreNonSpace`: `CompareOptions.IgnoreNonSpace` is mapped to `NSStringCompareOptions.NSDiacriticInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch` -- `IgnoreWidth` is mapped to `NSStringCompareOptions.NSWidthInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch` +- `IgnoreWidth`: + +`CompareOptions.IgnoreWidth` is mapped to `NSStringCompareOptions.NSWidthInsensitiveSearch | NSStringCompareOptions.NSLiteralSearch` - All combinations that contain below `CompareOptions` always throw `PlatformNotSupportedException`: diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs index fcf51f931cc411..eb4d7e94d80e85 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.Compare.cs @@ -195,7 +195,7 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.None, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "A\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.None, 1 }; - yield return new object[] { s_invariantCompare, "A\u0300", "a\u0300", CompareOptions.IgnoreCase, 0 }; + yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : 0 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.Ordinal, 1 }; yield return new object[] { s_invariantCompare, "\u00C0", "a\u0300", CompareOptions.OrdinalIgnoreCase, 1 }; yield return new object[] { s_invariantCompare, "FooBar", "Foo\u0400Bar", CompareOptions.Ordinal, -1 }; @@ -207,7 +207,6 @@ public static IEnumerable Compare_TestData() yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.IgnoreSymbols, 0 }; } yield return new object[] { s_invariantCompare, "Test's", "Tests", CompareOptions.StringSort, -1 }; - yield return new object[] { s_invariantCompare, "-a", "a-", CompareOptions.StringSort, -1 }; yield return new object[] { s_invariantCompare, null, "Tests", CompareOptions.None, -1 }; yield return new object[] { s_invariantCompare, "Test's", null, CompareOptions.None, 1 }; From e53aa0ca57f4f85424f0ebdf78549d9074afbd0f Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Mon, 22 May 2023 17:23:16 +0200 Subject: [PATCH 17/20] Added StringSort compare option --- .../libs/System.Globalization.Native/pal_collation.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 74317308cd8b55..9cc85e52bdf554 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -16,15 +16,15 @@ IgnoreCase = 1, IgnoreNonSpace = 2, IgnoreWidth = 16, + StringSort = 536870912, } CompareOptions; -#define CompareOptionsMask 0x1f - static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions(int32_t comparisonOptions) { - int32_t supportedOptions = IgnoreCase | IgnoreNonSpace | IgnoreWidth; + int32_t supportedOptions = IgnoreCase | IgnoreNonSpace | IgnoreWidth | StringSort; + // To achieve an equivalent search behavior to the default in ICU, + // NSLiteralSearch is employed as the default search option. NSStringCompareOptions options = NSLiteralSearch; - comparisonOptions &= CompareOptionsMask; if ((comparisonOptions | supportedOptions) != supportedOptions) return 0; From c316a2658c0cb540b1b77525adb2549f970c8ed4 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 23 May 2023 13:38:21 +0200 Subject: [PATCH 18/20] Refactoring requested by review --- .../src/Resources/Strings.resx | 4 ++-- .../src/System/Globalization/CompareInfo.OSX.cs | 13 ++++--------- .../System.Globalization.Native/pal_collation.m | 6 +++--- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 157621f7d8e0d6..f671c8327f22f5 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -4059,10 +4059,10 @@ AssemblyName.GetAssemblyName() is not supported on this platform. - CompareOptions = {0} are not supported when HybridGlobalization=true. Disable it to load larger ICU bundle, then use this option. + CompareOptions = {0} are not supported when HybridGlobalization=true on this platform. Disable it to load larger ICU bundle, then use this option. - CompareOptions = {0} are not supported for culture = {1} when HybridGlobalization=true. Disable it to load larger ICU bundle, then use this option. + CompareOptions = {0} are not supported for culture = {1} when HybridGlobalization=true on this platform. Disable it to load larger ICU bundle, then use this option. Match length calculation is not supported when HybridGlobalization=true. Disable it to load larger ICU bundle, then use this function. diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs index 87d3a9be3690fe..b96541580bc924 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CompareInfo.OSX.cs @@ -15,7 +15,6 @@ private unsafe int CompareStringNative(ReadOnlySpan string1, ReadOnlySpan< { Debug.Assert(!GlobalizationMode.Invariant); Debug.Assert(!GlobalizationMode.UseNls); - Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0); AssertComparisonSupported(options); @@ -28,23 +27,19 @@ private unsafe int CompareStringNative(ReadOnlySpan string1, ReadOnlySpan< result = Interop.Globalization.CompareStringNative(m_name, m_name.Length, pString1, string1.Length, pString2, string2.Length, options); } - if (result == -2) - { - throw new PlatformNotSupportedException(GetPNSE(options)); - } + Debug.Assert(result != -2); return result; } private static void AssertComparisonSupported(CompareOptions options) { - if (CompareOptionsNotSupported(options)) + if ((options | SupportedCompareOptions) != SupportedCompareOptions) throw new PlatformNotSupportedException(GetPNSE(options)); } - private static bool CompareOptionsNotSupported(CompareOptions options) => - (options & CompareOptions.IgnoreSymbols) == CompareOptions.IgnoreSymbols || - (options & CompareOptions.IgnoreKanaType) == CompareOptions.IgnoreKanaType; + private const CompareOptions SupportedCompareOptions = CompareOptions.None | CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace | + CompareOptions.IgnoreWidth | CompareOptions.StringSort; private static string GetPNSE(CompareOptions options) => SR.Format(SR.PlatformNotSupported_HybridGlobalizationWithCompareOptions, options); diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 9cc85e52bdf554..8dcd927e646c9c 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -21,7 +21,7 @@ static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions(int32_t comparisonOptions) { - int32_t supportedOptions = IgnoreCase | IgnoreNonSpace | IgnoreWidth | StringSort; + int32_t supportedOptions = None | IgnoreCase | IgnoreNonSpace | IgnoreWidth | StringSort; // To achieve an equivalent search behavior to the default in ICU, // NSLiteralSearch is employed as the default search option. NSStringCompareOptions options = NSLiteralSearch; @@ -41,8 +41,6 @@ static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions( return options; } -#endif - /* Function: CompareString @@ -75,3 +73,5 @@ int32_t GlobalizationNative_CompareStringNative(const char* localeName, int32_t range:string1Range locale:currentLocale]; } + +#endif From 199c27e52d8d96fb11e52330f7126caf9ba08c2e Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 23 May 2023 17:27:48 +0200 Subject: [PATCH 19/20] Parameter type changed from char* to unichar* --- .../libs/System.Globalization.Native/pal_collation.h | 6 +++--- .../libs/System.Globalization.Native/pal_collation.m | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/native/libs/System.Globalization.Native/pal_collation.h b/src/native/libs/System.Globalization.Native/pal_collation.h index b38f97960d0dbe..a7940ba5ef9d8a 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.h +++ b/src/native/libs/System.Globalization.Native/pal_collation.h @@ -63,11 +63,11 @@ PALEXPORT int32_t GlobalizationNative_GetSortKey(SortHandle* pSortHandle, int32_t options); #ifdef __APPLE__ -PALEXPORT int32_t GlobalizationNative_CompareStringNative(const char* localeName, +PALEXPORT int32_t GlobalizationNative_CompareStringNative(const unsigned short* localeName, int32_t lNameLength, - const char* lpStr1, + const unsigned short* lpStr1, int32_t cwStr1Length, - const char* lpStr2, + const unsigned short* lpStr2, int32_t cwStr2Length, int32_t options); #endif diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index 8dcd927e646c9c..ebd40dce1a59b5 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -45,8 +45,8 @@ static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions( Function: CompareString */ -int32_t GlobalizationNative_CompareStringNative(const char* localeName, int32_t lNameLength, const char* lpStr1, int32_t cwStr1Length, - const char* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) +int32_t GlobalizationNative_CompareStringNative(const unichar* localeName, int32_t lNameLength, const unichar* lpStr1, int32_t cwStr1Length, + const unichar* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) { NSLocale *currentLocale; if(localeName == NULL || lNameLength == 0) @@ -55,12 +55,12 @@ int32_t GlobalizationNative_CompareStringNative(const char* localeName, int32_t } else { - NSString *locName = [NSString stringWithCharacters: (const unichar *)localeName length: lNameLength]; + NSString *locName = [NSString stringWithCharacters: localeName length: lNameLength]; currentLocale = [[NSLocale alloc] initWithLocaleIdentifier:locName]; } - NSString *firstString = [NSString stringWithCharacters: (const unichar *)lpStr1 length: cwStr1Length]; - NSString *secondString = [NSString stringWithCharacters: (const unichar *)lpStr2 length: cwStr2Length]; + NSString *firstString = [NSString stringWithCharacters: lpStr1 length: cwStr1Length]; + NSString *secondString = [NSString stringWithCharacters: lpStr2 length: cwStr2Length]; NSRange string1Range = NSMakeRange(0, cwStr1Length); NSStringCompareOptions options = ConvertFromCompareOptionsToNSStringCompareOptions(comparisonOptions); From b0cbfac7fc4d93db7328ac177091a270694fc63f Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 24 May 2023 10:16:30 +0200 Subject: [PATCH 20/20] use const uint16_t * in both .h and .m --- src/native/libs/System.Globalization.Native/pal_collation.h | 6 +++--- src/native/libs/System.Globalization.Native/pal_collation.m | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/native/libs/System.Globalization.Native/pal_collation.h b/src/native/libs/System.Globalization.Native/pal_collation.h index a7940ba5ef9d8a..2aaff773dd449d 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.h +++ b/src/native/libs/System.Globalization.Native/pal_collation.h @@ -63,11 +63,11 @@ PALEXPORT int32_t GlobalizationNative_GetSortKey(SortHandle* pSortHandle, int32_t options); #ifdef __APPLE__ -PALEXPORT int32_t GlobalizationNative_CompareStringNative(const unsigned short* localeName, +PALEXPORT int32_t GlobalizationNative_CompareStringNative(const uint16_t* localeName, int32_t lNameLength, - const unsigned short* lpStr1, + const uint16_t* lpStr1, int32_t cwStr1Length, - const unsigned short* lpStr2, + const uint16_t* lpStr2, int32_t cwStr2Length, int32_t options); #endif diff --git a/src/native/libs/System.Globalization.Native/pal_collation.m b/src/native/libs/System.Globalization.Native/pal_collation.m index ebd40dce1a59b5..f0120e5708f163 100644 --- a/src/native/libs/System.Globalization.Native/pal_collation.m +++ b/src/native/libs/System.Globalization.Native/pal_collation.m @@ -45,8 +45,8 @@ static NSStringCompareOptions ConvertFromCompareOptionsToNSStringCompareOptions( Function: CompareString */ -int32_t GlobalizationNative_CompareStringNative(const unichar* localeName, int32_t lNameLength, const unichar* lpStr1, int32_t cwStr1Length, - const unichar* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) +int32_t GlobalizationNative_CompareStringNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* lpStr1, int32_t cwStr1Length, + const uint16_t* lpStr2, int32_t cwStr2Length, int32_t comparisonOptions) { NSLocale *currentLocale; if(localeName == NULL || lNameLength == 0)