From 7eccecfbf843033aabdb70677656b1337590cd31 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Thu, 26 Oct 2023 15:07:57 +0200 Subject: [PATCH 1/8] Implement missing functions in locale --- .../Common/src/Interop/Interop.Casing.iOS.cs | 3 + .../Common/src/Interop/Interop.Locale.iOS.cs | 15 ++- .../TestUtilities/System/PlatformDetection.cs | 4 + .../CompareInfo/CompareInfoTests.IsSuffix.cs | 2 +- .../tests/CompareInfo/CompareInfoTests.cs | 16 +-- .../tests/CompareInfo/CompareInfoTestsBase.cs | 1 + .../tests/CultureInfo/CultureInfoAll.cs | 7 +- .../tests/CultureInfo/CultureInfoCtor.cs | 50 ++++---- .../tests/CultureInfo/GetCultureInfo.cs | 23 +++- ...DateTimeFormatInfoGetAbbreviatedEraName.cs | 2 +- .../DateTimeFormatInfoGetEra.cs | 2 +- .../System.Globalization.IOS.Tests.csproj | 121 +++++++++++++----- .../System.Globalization/tests/IcuTests.cs | 2 +- .../NumberFormatInfo/NumberFormatInfoData.cs | 2 +- .../System/Globalization/RegionInfoTests.cs | 8 +- .../System/Globalization/CultureData.Icu.cs | 25 ++++ .../System/Globalization/CultureData.Unix.cs | 7 +- .../System/Globalization/CultureData.iOS.cs | 14 -- .../System/Globalization/CultureInfo.Unix.cs | 17 ++- .../System/Globalization/OrdinalCasing.Icu.cs | 11 ++ .../System.Globalization.Native/entrypoints.c | 1 + .../System.Globalization.Native/pal_casing.h | 2 + .../System.Globalization.Native/pal_casing.m | 21 +++ .../System.Globalization.Native/pal_locale.h | 4 + .../System.Globalization.Native/pal_locale.m | 45 +++++++ 25 files changed, 301 insertions(+), 104 deletions(-) diff --git a/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs b/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs index 5e0140faa4c43e..19372c62907453 100644 --- a/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs +++ b/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs @@ -12,5 +12,8 @@ internal static partial class Globalization [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_ChangeCaseInvariantNative", StringMarshalling = StringMarshalling.Utf8)] internal static unsafe partial int ChangeCaseInvariantNative(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, [MarshalAs(UnmanagedType.Bool)] bool bToUpper); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_InitOrdinalCasingPageNative", StringMarshalling = StringMarshalling.Utf16)] + internal static unsafe partial void InitOrdinalCasingPageNative(int pageNumber, char* pTarget); } } diff --git a/src/libraries/Common/src/Interop/Interop.Locale.iOS.cs b/src/libraries/Common/src/Interop/Interop.Locale.iOS.cs index 6725436b4f0945..3062de8918dc37 100644 --- a/src/libraries/Common/src/Interop/Interop.Locale.iOS.cs +++ b/src/libraries/Common/src/Interop/Interop.Locale.iOS.cs @@ -7,8 +7,8 @@ internal static partial class Interop { internal static partial class Globalization { - [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)] - internal static partial string GetLocaleNameNative(string localeName); + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetDefaultLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)] + internal static partial string GetDefaultLocaleNameNative(); [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoStringNative", StringMarshalling = StringMarshalling.Utf8)] internal static partial string GetLocaleInfoStringNative(string localeName, uint localeStringData); @@ -22,10 +22,17 @@ internal static partial class Globalization [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleInfoSecondaryGroupingSizeNative", StringMarshalling = StringMarshalling.Utf8)] internal static partial int GetLocaleInfoSecondaryGroupingSizeNative(string localeName, uint localeGroupingData); - [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleTimeFormatNative", StringMarshalling = StringMarshalling.Utf8)] - internal static partial string GetLocaleTimeFormatNative(string localeName, [MarshalAs(UnmanagedType.Bool)] bool shortFormat); + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleNameNative", StringMarshalling = StringMarshalling.Utf8)] + internal static partial string GetLocaleNameNative(string localeName); [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocalesNative", StringMarshalling = StringMarshalling.Utf16)] internal static partial int GetLocalesNative([Out] char[]? value, int valueLength); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetLocaleTimeFormatNative", StringMarshalling = StringMarshalling.Utf8)] + internal static partial string GetLocaleTimeFormatNative(string localeName, [MarshalAs(UnmanagedType.Bool)] bool shortFormat); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_IsPredefinedLocaleNative", StringMarshalling = StringMarshalling.Utf8)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool IsPredefinedLocaleNative(string localeName); } } diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 394e0b84682e3e..3738c5aede333b 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -365,12 +365,16 @@ public static string GetDistroVersionString() public static Version ICUVersion => m_icuVersion.Value; public static bool IsInvariantGlobalization => m_isInvariant.Value; + public static bool IsHybridGlobalization => m_isHybrid.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 IsNotHybridGlobalization => !IsHybridGlobalization; + public static bool IsNotHybridGlobalizationOnOSX => !IsHybridGlobalizationOnOSX; public static bool IsIcuGlobalization => ICUVersion > new Version(0, 0, 0, 0); public static bool IsIcuGlobalizationAndNotHybridOnBrowser => IsIcuGlobalization && IsNotHybridGlobalizationOnBrowser; + public static bool IsIcuGlobalizationAndNotHybrid => IsIcuGlobalization && IsNotHybridGlobalizationOnBrowser && IsNotHybridGlobalizationOnOSX; public static bool IsNlsGlobalization => IsNotInvariantGlobalization && !IsIcuGlobalization; public static bool IsSubstAvailable diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IsSuffix.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IsSuffix.cs index 8b83094efe3be8..906392ba3fed9e 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IsSuffix.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.IsSuffix.cs @@ -162,7 +162,7 @@ public void IsSuffix(CompareInfo compareInfo, string source, string value, Compa [Fact] public void IsSuffix_UnassignedUnicode() { - bool result = PlatformDetection.IsIcuGlobalization ? false : true; + bool result = PlatformDetection.IsIcuGlobalization || PlatformDetection.IsHybridGlobalizationOnOSX ? false : true; int expectedMatchLength = (result) ? 6 : 0; IsSuffix(s_invariantCompare, "FooBar", "Foo\uFFFFBar", CompareOptions.None, result, expectedMatchLength); diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.cs index 24ef09380db068..cbd011b96fa0cb 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTests.cs @@ -60,7 +60,7 @@ public void EqualsTest(CompareInfo compare1, object value, bool expected) new object[] { "", CompareOptions.None, "\u200c", CompareOptions.None, true }, // see comment at bottom of SortKey_TestData }; - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalization))] [MemberData(nameof(GetHashCodeTestData))] public void GetHashCodeTest(string source1, CompareOptions options1, string source2, CompareOptions options2, bool expected) { @@ -345,14 +345,14 @@ public static void LcidTest(string cultureName, int lcid) Assert.Equal(lcid, ci.LCID); } - [ConditionalTheory(typeof(CompareInfoTests), nameof(IsNotWindowsKanaRegressedVersionAndNotHybridGlobalizationOnWasm))] + [ConditionalTheory(typeof(CompareInfoTests), nameof(IsNotWindowsKanaRegressedVersionAndNotHybridGlobalization))] [MemberData(nameof(SortKey_Kana_TestData))] public void SortKeyKanaTest(CompareInfo compareInfo, string string1, string string2, CompareOptions options, int expected) { SortKeyTest(compareInfo, string1, string2, options, expected); } - [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalizationOnBrowser))] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsHybridGlobalization))] public void SortKeyTestNotSupported() { try @@ -395,7 +395,7 @@ public void SortKeyTestNotSupported() private static bool WindowsVersionHasTheCompareStringRegression => PlatformDetection.IsNlsGlobalization && CompareStringEx("", NORM_LINGUISTIC_CASING, "", 0, "\u200C", 1, IntPtr.Zero, IntPtr.Zero, 0) != 2; - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalization))] [MemberData(nameof(SortKey_TestData))] public void SortKeyTest(CompareInfo compareInfo, string string1, string string2, CompareOptions options, int expectedSign) { @@ -444,7 +444,7 @@ unsafe static void RunSpanSortKeyTest(CompareInfo compareInfo, ReadOnlySpan !PlatformDetection.I s_invariantCompare.Compare("\u3060", "\uFF80\uFF9E", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase) == 0; protected static bool IsNotWindowsKanaRegressedVersionAndNotHybridGlobalizationOnWasm() => !PlatformDetection.IsHybridGlobalizationOnBrowser && IsNotWindowsKanaRegressedVersion(); + protected static bool IsNotWindowsKanaRegressedVersionAndNotHybridGlobalization() => IsNotWindowsKanaRegressedVersionAndNotHybridGlobalizationOnWasm() && !PlatformDetection.IsHybridGlobalizationOnOSX; } } diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs index fb4692da1a0abc..c707ff005faf3f 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoAll.cs @@ -635,13 +635,11 @@ public static IEnumerable CultureInfo_TestData() yield return new object[] { 0x2009, new [] { "en-jm" }, "en-JM", "eng", "ENJ", "en-JM", "en-JM" }; yield return new object[] { 0x241a, new [] { "sr-latn-rs" }, "sr-Latn-RS", "srp", "SRM", "sr-Latn-RS", "sr-Latn-RS" }; yield return new object[] { 0x2809, new [] { "en-bz" }, "en-BZ", "eng", "ENL", "en-BZ", "en-BZ" }; - yield return new object[] { 0x281a, new [] { "sr-cyrl-rs" }, "sr-Cyrl-RS", "srp", "SRO", "sr-Cyrl-RS", "sr-Cyrl-RS" }; yield return new object[] { 0x2c09, new [] { "en-tt" }, "en-TT", "eng", "ENT", "en-TT", "en-TT" }; yield return new object[] { 0x3009, new [] { "en-zw" }, "en-ZW", "eng", "ENW", "en-ZW", "en-ZW" }; yield return new object[] { 0x3409, new [] { "en-ph" }, "en-PH", "eng", "ENP", "en-PH", "en-PH" }; yield return new object[] { 0x4009, new [] { "en-in" }, "en-IN", "eng", "ENN", "en-IN", "en-IN" }; yield return new object[] { 0x4809, new [] { "en-sg" }, "en-SG", "eng", "ENE", "en-SG", "en-SG" }; - yield return new object[] { 0x6c1a, new [] { "sr-cyrl" }, "sr-Cyrl-RS", "srp", "SRO", "sr-Cyrl", "sr-Cyrl-RS" }; yield return new object[] { 0x701a, new [] { "sr-latn" }, "sr-Latn-RS", "srp", "SRM", "sr-Latn", "sr-Latn-RS" }; yield return new object[] { 0x7804, new [] { "zh" }, "zh-CN", "zho", "CHS", "zh", "zh-CN" }; yield return new object[] { 0x7c04, new [] { "zh-cht", "zh-hant" }, "zh-HK", "zho", "CHT", "zh-Hant", "zh-HK" }; @@ -654,6 +652,11 @@ public static IEnumerable CultureInfo_TestData() yield return new object[] { 0x40404, new [] { "zh-tw_radstr", "zh-tw" }, "zh-TW", "zho", "CHT", "zh-Hant-TW", "zh-TW" }; yield return new object[] { 0x40411, new [] { "ja-jp_radstr", "ja-jp" }, "ja-JP", "jpn", "JPN", "ja-JP", "ja-JP" }; yield return new object[] { 0x40c04, new [] { "zh-hk_radstr", "zh-hk" }, "zh-HK", "zho", "ZHH", "zh-Hant-HK", "zh-HK" }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { 0x281a, new [] { "sr-cyrl-rs" }, "sr-Cyrl-RS", "srp", "SRO", "sr-Cyrl-RS", "sr-Cyrl-RS" }; + yield return new object[] { 0x6c1a, new [] { "sr-cyrl" }, "sr-Cyrl-RS", "srp", "SRO", "sr-Cyrl", "sr-Cyrl-RS" }; + } } [Theory] diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs index 37175600777b43..9edf9c5dfe6cfc 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs @@ -40,8 +40,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "az", new [] { "az" }}; yield return new object[] { "az-Cyrl", new [] { "az-Cyrl" }}; yield return new object[] { "az-Cyrl-AZ", new [] { "az-Cyrl-AZ" }}; - yield return new object[] { "az-Latn", new [] { "az-Latn" }}; - yield return new object[] { "az-Latn-AZ", new [] { "az-Latn-AZ" }}; yield return new object[] { "ba", new [] { "ba" }}; yield return new object[] { "ba-RU", new [] { "ba-RU" }}; yield return new object[] { "be", new [] { "be" }}; @@ -58,8 +56,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "bs", new [] { "bs" }}; yield return new object[] { "bs-Cyrl", new [] { "bs-Cyrl" }}; yield return new object[] { "bs-Cyrl-BA", new [] { "bs-Cyrl-BA" }}; - yield return new object[] { "bs-Latn", new [] { "bs-Latn" }}; - yield return new object[] { "bs-Latn-BA", new [] { "bs-Latn-BA" }}; yield return new object[] { "ca", new [] { "ca" } }; yield return new object[] { "ca-ES", new [] { "ca-ES" } }; yield return new object[] { "co", new [] { "co" }}; @@ -154,8 +150,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "gu", new [] { "gu" } }; yield return new object[] { "gu-IN", new [] { "gu-IN" } }; yield return new object[] { "ha", new [] { "ha" }}; - yield return new object[] { "ha-Latn", new [] { "ha-Latn" }}; - yield return new object[] { "ha-Latn-NG", new [] { "ha-Latn-NG" }}; yield return new object[] { "he", new [] { "he" } }; yield return new object[] { "he-IL", new [] { "he-IL" } }; yield return new object[] { "hi", new [] { "hi" } }; @@ -221,7 +215,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "ml", new [] { "ml" } }; yield return new object[] { "ml-IN", new [] { "ml-IN" } }; yield return new object[] { "mn", new [] { "mn" }}; - yield return new object[] { "mn-Cyrl", new [] { "mn-Cyrl" }}; yield return new object[] { "mn-MN", new [] { "mn-MN" }}; yield return new object[] { "mn-Mong", new [] { "mn-Mong" }}; yield return new object[] { "mn-Mong-CN", new [] { "mn-Mong-CN" }}; @@ -243,7 +236,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "nl-NL", new [] { "nl-NL" } }; yield return new object[] { "nn", new [] { "nn" }}; yield return new object[] { "nn-NO", new [] { "nn-NO" }}; - yield return new object[] { "no", new [] { "no" } }; yield return new object[] { "nso", new [] { "nso" }}; yield return new object[] { "nso-ZA", new [] { "nso-ZA" }}; yield return new object[] { "oc", new [] { "oc" }}; @@ -300,14 +292,8 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "sq", new [] { "sq" }}; yield return new object[] { "sq-AL", new [] { "sq-AL" }}; yield return new object[] { "sr", new [] { "sr" } }; - yield return new object[] { "sr-Cyrl", new [] { "sr-Cyrl" } }; - yield return new object[] { "sr-Cyrl-BA", new [] { "sr-Cyrl-BA" }}; - yield return new object[] { "sr-Cyrl-CS", new [] { "sr-Cyrl-CS" }}; - yield return new object[] { "sr-Cyrl-ME", new [] { "sr-Cyrl-ME" }}; - yield return new object[] { "sr-Cyrl-RS", new [] { "sr-Cyrl-RS" } }; yield return new object[] { "sr-Latn", new [] { "sr-Latn" } }; yield return new object[] { "sr-Latn-BA", new [] { "sr-Latn-BA" }}; - yield return new object[] { "sr-Latn-CS", new [] { "sr-Latn-CS" }}; yield return new object[] { "sr-Latn-ME", new [] { "sr-Latn-ME" }}; yield return new object[] { "sr-Latn-RS", new [] { "sr-Latn-RS" } }; yield return new object[] { "sv", new [] { "sv" } }; @@ -322,8 +308,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "te", new [] { "te" } }; yield return new object[] { "te-IN", new [] { "te-IN" } }; yield return new object[] { "tg", new [] { "tg" }}; - yield return new object[] { "tg-Cyrl", new [] { "tg-Cyrl" }}; - yield return new object[] { "tg-Cyrl-TJ", new [] { "tg-Cyrl-TJ" }}; yield return new object[] { "th", new [] { "th" } }; yield return new object[] { "th-TH", new [] { "th-TH" } }; yield return new object[] { "tk", new [] { "tk" }}; @@ -335,8 +319,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "tt", new [] { "tt" }}; yield return new object[] { "tt-RU", new [] { "tt-RU" }}; yield return new object[] { "tzm", new [] { "tzm" }}; - yield return new object[] { "tzm-Latn", new [] { "tzm-Latn" }}; - yield return new object[] { "tzm-Latn-DZ", new [] { "tzm-Latn-DZ" }}; yield return new object[] { "ug", new [] { "ug" }}; yield return new object[] { "ug-CN", new [] { "ug-CN" }}; yield return new object[] { "uk", new [] { "uk" } }; @@ -346,8 +328,6 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "uz", new [] { "uz" }}; yield return new object[] { "uz-Cyrl", new [] { "uz-Cyrl" }}; yield return new object[] { "uz-Cyrl-UZ", new [] { "uz-Cyrl-UZ" }}; - yield return new object[] { "uz-Latn", new [] { "uz-Latn" }}; - yield return new object[] { "uz-Latn-UZ", new [] { "uz-Latn-UZ" }}; yield return new object[] { "vi", new [] { "vi" } }; yield return new object[] { "vi-VN", new [] { "vi-VN" } }; yield return new object[] { "wo", new [] { "wo" }}; @@ -377,6 +357,30 @@ public static IEnumerable Ctor_String_TestData() yield return new object[] { "zu-ZA", new [] { "zu-ZA" }}; yield return new object[] { CultureInfo.CurrentCulture.Name, new [] { CultureInfo.CurrentCulture.Name } }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { "az-Latn", new [] { "az-Latn" }}; + yield return new object[] { "az-Latn-AZ", new [] { "az-Latn-AZ" }}; + yield return new object[] { "bs-Latn", new [] { "bs-Latn" }}; + yield return new object[] { "bs-Latn-BA", new [] { "bs-Latn-BA" }}; + yield return new object[] { "ha-Latn", new [] { "ha-Latn" }}; + yield return new object[] { "ha-Latn-NG", new [] { "ha-Latn-NG" }}; + yield return new object[] { "mn-Cyrl", new [] { "mn-Cyrl" }}; + yield return new object[] { "no", new [] { "no" } }; + yield return new object[] { "sr-Cyrl", new [] { "sr-Cyrl" } }; + yield return new object[] { "sr-Cyrl-BA", new [] { "sr-Cyrl-BA" }}; + yield return new object[] { "sr-Cyrl-CS", new [] { "sr-Cyrl-CS" }}; + yield return new object[] { "sr-Cyrl-ME", new [] { "sr-Cyrl-ME" }}; + yield return new object[] { "sr-Cyrl-RS", new [] { "sr-Cyrl-RS" } }; + yield return new object[] { "sr-Latn-CS", new [] { "sr-Latn-CS" }}; + yield return new object[] { "tg-Cyrl", new [] { "tg-Cyrl" }}; + yield return new object[] { "tg-Cyrl-TJ", new [] { "tg-Cyrl-TJ" }}; + yield return new object[] { "tzm-Latn", new [] { "tzm-Latn" }}; + yield return new object[] { "tzm-Latn-DZ", new [] { "tzm-Latn-DZ" }}; + yield return new object[] { "uz-Latn", new [] { "uz-Latn" }}; + yield return new object[] { "uz-Latn-UZ", new [] { "uz-Latn-UZ" }}; + } + if ((!PlatformDetection.IsWindows || PlatformDetection.WindowsVersion >= 10) && (PlatformDetection.IsNotBrowser)) { yield return new object[] { "en-US-CUSTOM", new [] { "en-US-CUSTOM", "en-US-custom" } }; @@ -396,7 +400,7 @@ public void Ctor_String(string name, string[] expectedNames) Assert.Equal(cultureName, culture.ToString(), ignoreCase: true); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnOSX))] public void Ctor_String_Invalid() { AssertExtensions.Throws("name", () => new CultureInfo(null)); // Name is null @@ -442,7 +446,7 @@ public void TestCreationWithTemporaryLCID(int lcid) [InlineData("de-DE-u-co-phonebk-t-xx", "de-DE-t-xx", "de-DE-t-xx_phoneboo")] [InlineData("de-DE-u-co-phonebk-t-xx-u-yy", "de-DE-t-xx-u-yy", "de-DE-t-xx-u-yy_phoneboo")] [InlineData("de-DE", "de-DE", "de-DE")] - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalizationAndNotHybridOnBrowser))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalizationAndNotHybrid))] public void TestCreationWithMangledSortName(string cultureName, string expectedCultureName, string expectedSortName) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); @@ -457,7 +461,7 @@ public void TestCreationWithMangledSortName(string cultureName, string expectedC [InlineData("qps-plocm", "qps-PLOCM")] // ICU normalize this name to "qps--plocm" which we normalize it back to "qps-plocm" [InlineData("zh_CN", "zh_cn")] [InlineData("km_KH", "km_kh")] - [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalizationAndNotHybridOnBrowser), nameof(PlatformDetection.IsNotWindowsServerCore))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalizationAndNotHybrid), nameof(PlatformDetection.IsNotWindowsServerCore))] public void TestCreationWithICUNormalizedNames(string cultureName, string expectedCultureName) { CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); diff --git a/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs b/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs index 0e7873853ebd70..a1dc7c2c9c7a8e 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/GetCultureInfo.cs @@ -21,7 +21,10 @@ public static IEnumerable GetCultureInfoTestData() yield return new object[] { "ja-JP" }; yield return new object[] { "ar-SA" }; yield return new object[] { "xx-XX" }; - yield return new object[] { "de-AT-1901" }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { "de-AT-1901" }; + } yield return new object[] { "zh-Hans" }; yield return new object[] { "zh-Hans-HK" }; yield return new object[] { "zh-Hans-MO" }; @@ -30,16 +33,22 @@ public static IEnumerable GetCultureInfoTestData() yield return new object[] { "zh-Hant-CN" }; yield return new object[] { "zh-Hant-SG" }; - if (PlatformDetection.IsIcuGlobalization) + if (PlatformDetection.IsIcuGlobalization || PlatformDetection.IsHybridGlobalizationOnOSX) { if (PlatformDetection.IsNotWindows) { yield return new object[] { "x\u0000X-Yy", "x" }; // Null byte - yield return new object[] { "zh-cmn", "zh-CMN" }; - yield return new object[] { "zh-CMN-HANS" }; - yield return new object[] { "zh-cmn-Hant", "zh-CMN-HANT" }; + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { "zh-cmn", "zh-CMN" }; + yield return new object[] { "zh-CMN-HANS" }; + yield return new object[] { "zh-cmn-Hant", "zh-CMN-HANT" }; + } + } + if (!PlatformDetection.IsHybridGlobalizationOnOSX) + { + yield return new object[] { "sgn-BE-FR" }; } - yield return new object[] { "sgn-BE-FR" }; yield return new object[] { "zh-min-nan", "nan" }; yield return new object[] { "zh-gan", "gan" }; yield return new object[] { "zh-Hans-CN" }; @@ -98,7 +107,7 @@ public void GetCultureInfo(string name, string expected = null) [InlineData("foo_-bar")] [InlineData("foo/bar")] [InlineData("/")] - [InlineData("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234")] // > 85 characters + [InlineData("01234567890123456789012345678901234567890123456789012345678901234567890123456789012345")] // > 85 characters public void TestInvalidCultureNames(string name) { Assert.Throws(() => CultureInfo.GetCultureInfo(name)); diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs index 0efefdd7d6a69b..8dd07f32a85bcb 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetAbbreviatedEraName.cs @@ -208,7 +208,7 @@ public static IEnumerable GetAbbreviatedEraName_TestData() } } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnOSX))] [MemberData(nameof(GetAbbreviatedEraName_TestData))] public void GetAbbreviatedEraName_Invoke_ReturnsExpected(DateTimeFormatInfo format, int era, string expected) { diff --git a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetEra.cs b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetEra.cs index e4c75e1bb7601f..6182546199a920 100644 --- a/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetEra.cs +++ b/src/libraries/System.Globalization/tests/DateTimeFormatInfo/DateTimeFormatInfoGetEra.cs @@ -49,7 +49,7 @@ public static IEnumerable GetEra_TestData() yield return new object[] { frFRFormat, "ap J-C", -1 }; } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotHybridGlobalizationOnOSX))] [MemberData(nameof(GetEra_TestData))] public void GetEra_Invoke_ReturnsExpected(DateTimeFormatInfo format, string eraName, int expected) { diff --git a/src/libraries/System.Globalization/tests/Hybrid/System.Globalization.IOS.Tests.csproj b/src/libraries/System.Globalization/tests/Hybrid/System.Globalization.IOS.Tests.csproj index bb38f00b88f9d8..e0ff97362fe7e4 100644 --- a/src/libraries/System.Globalization/tests/Hybrid/System.Globalization.IOS.Tests.csproj +++ b/src/libraries/System.Globalization/tests/Hybrid/System.Globalization.IOS.Tests.csproj @@ -3,22 +3,65 @@ $(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst true true + true + true + 15.0 - - - - - - - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -31,8 +74,10 @@ + + @@ -52,28 +97,44 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - + + + + + + + + + + + + + + + + + CharUnicodeInfo\UnicodeData.$(UnicodeUcdVersion).txt + UnicodeData.txt + + + CharUnicodeInfo\GraphemeBreakTest-$(UnicodeUcdVersion).0.txt + GraphemeBreakTest.txt + + + + diff --git a/src/libraries/System.Globalization/tests/IcuTests.cs b/src/libraries/System.Globalization/tests/IcuTests.cs index 0990c710f6d63b..05b0e950d74321 100644 --- a/src/libraries/System.Globalization/tests/IcuTests.cs +++ b/src/libraries/System.Globalization/tests/IcuTests.cs @@ -9,7 +9,7 @@ namespace System.Globalization.Tests { public class IcuTests { - private static bool IsIcuCompatiblePlatform => PlatformDetection.IsNotWindows || + private static bool IsIcuCompatiblePlatform => !PlatformDetection.IsHybridGlobalizationOnOSX && PlatformDetection.IsNotWindows || ((PlatformDetection.IsWindowsServer2019 || PlatformDetection.IsWindows10Version1903OrGreater) && // Server core doesn't have icu.dll on SysWOW64 !(PlatformDetection.IsWindowsServerCore && PlatformDetection.IsX86Process)); diff --git a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs index 36ff2977b807d1..96911b398714bf 100644 --- a/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs +++ b/src/libraries/System.Globalization/tests/NumberFormatInfo/NumberFormatInfoData.cs @@ -7,7 +7,7 @@ internal static class NumberFormatInfoData { public static int[] UrINNumberGroupSizes() { - if (PlatformDetection.WindowsVersion >= 10 || PlatformDetection.ICUVersion.Major >= 55) + if (PlatformDetection.WindowsVersion >= 10 || PlatformDetection.ICUVersion.Major >= 55 || PlatformDetection.IsHybridGlobalizationOnOSX) { return new int[] { 3 }; } diff --git a/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs b/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs index 6fd30317d7f06b..a5e4641290aade 100644 --- a/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs +++ b/src/libraries/System.Globalization/tests/System/Globalization/RegionInfoTests.cs @@ -112,7 +112,7 @@ public void DisplayName(string name, string expected) public static IEnumerable NativeName_TestData() { // Android has its own ICU, which doesn't 100% map to UsingLimitedCultures - if (PlatformDetection.IsNotUsingLimitedCultures || PlatformDetection.IsAndroid) + if (PlatformDetection.IsNotUsingLimitedCultures || PlatformDetection.IsAndroid || PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { "GB", "United Kingdom" }; yield return new object[] { "SE", "Sverige" }; @@ -137,7 +137,7 @@ public void NativeName(string name, string expected) public static IEnumerable EnglishName_TestData() { // Android has its own ICU, which doesn't 100% map to UsingLimitedCultures - if (PlatformDetection.IsNotUsingLimitedCultures || PlatformDetection.IsAndroid) + if (PlatformDetection.IsNotUsingLimitedCultures || PlatformDetection.IsAndroid || PlatformDetection.IsHybridGlobalizationOnOSX) { yield return new object[] { "en-US", new string[] { "United States" } }; yield return new object[] { "US", new string[] { "United States" } }; @@ -208,7 +208,7 @@ public static IEnumerable RegionInfo_TestData() "SAU", "SAU" }; yield return new object[] { 0x412, 134, "South Korean Won", "KRW", "Korean Won", PlatformDetection.IsNlsGlobalization ? "\uc6d0" : "\ub300\ud55c\ubbfc\uad6d\u0020\uc6d0", "KOR", "KOR" }; yield return new object[] { 0x40d, 117, "Israeli New Shekel", "ILS", "Israeli New Sheqel", - PlatformDetection.IsNlsGlobalization || PlatformDetection.ICUVersion.Major >= 58 ? "\u05e9\u05e7\u05dc\u0020\u05d7\u05d3\u05e9" : "\u05e9\u05f4\u05d7", "ISR", "ISR" }; + PlatformDetection.IsNlsGlobalization || PlatformDetection.ICUVersion.Major >= 58 || PlatformDetection.IsHybridGlobalizationOnOSX ? "\u05e9\u05e7\u05dc\u0020\u05d7\u05d3\u05e9" : "\u05e9\u05f4\u05d7", "ISR", "ISR" }; } [Theory] @@ -219,7 +219,7 @@ public void MiscTest(int lcid, int geoId, string currencyEnglishName, string cur Assert.Equal(geoId, ri.GeoId); // Android has its own ICU, which doesn't 100% map to UsingLimitedCultures - if (PlatformDetection.IsUsingLimitedCultures && !PlatformDetection.IsAndroid) + if (PlatformDetection.IsUsingLimitedCultures && !PlatformDetection.IsAndroid && !PlatformDetection.IsHybridGlobalizationOnOSX) { Assert.Equal(currencyShortName, ri.CurrencyEnglishName); Assert.Equal(currencyShortName, ri.CurrencyNativeName); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 12af791d392e24..97422b35bf96b6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -120,11 +120,30 @@ private bool InitIcuCultureDataCore() realNameBuffer = string.Concat(realNameBuffer.AsSpan(0, index), ICU_COLLATION_KEYWORD, alternateSortName); } +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + { + _sWindowsName = GetLocaleNameNative(realNameBuffer); + if (_sWindowsName == null || _sWindowsName.Length == 0) + { + return false; + } + } + else + { + // Get the locale name from ICU + if (!GetLocaleName(realNameBuffer, out _sWindowsName)) + { + return false; + } + } +#else // Get the locale name from ICU if (!GetLocaleName(realNameBuffer, out _sWindowsName)) { return false; // fail } +#endif Debug.Assert(_sWindowsName != null); @@ -287,6 +306,12 @@ private unsafe string IcuGetTimeFormatString(bool shortFormat) internal static bool IcuIsEnsurePredefinedLocaleName(string name) { Debug.Assert(!GlobalizationMode.UseNls); +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + { + return Interop.Globalization.IsPredefinedLocaleNative(name); + } +#endif return Interop.Globalization.IsPredefinedLocale(name); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs index 533e97b3127d35..6291881ba96e09 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Unix.cs @@ -7,12 +7,7 @@ namespace System.Globalization { internal sealed partial class CultureData { - private bool InitCultureDataCore() => -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - GlobalizationMode.Hybrid ? InitAppleCultureDataCore() : InitIcuCultureDataCore(); -#else - InitIcuCultureDataCore(); -#endif + private bool InitCultureDataCore() => InitIcuCultureDataCore(); // Unix doesn't support user overrides partial void InitUserOverride(bool useUserOverride); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.iOS.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.iOS.cs index cdbdd65a81426f..6e1b43bfd08986 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.iOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.iOS.cs @@ -9,20 +9,6 @@ internal sealed partial class CultureData { private const int LOC_FULLNAME_CAPACITY = 157; // max size of locale name - /// - /// This method uses the sRealName field (which is initialized by the constructor before this is called) to - /// initialize the rest of the state of CultureData based on the underlying OS globalization library. - /// - private bool InitAppleCultureDataCore() - { - Debug.Assert(_sRealName != null); - Debug.Assert(!GlobalizationMode.Invariant); - string realNameBuffer = _sRealName; - - _sWindowsName = _sName = _sRealName = GetLocaleNameNative(realNameBuffer); - return true; - } - internal static string GetLocaleNameNative(string localeName) { return Interop.Globalization.GetLocaleNameNative(localeName); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs index a35b88c220609f..361c218da20775 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs @@ -13,7 +13,22 @@ internal static CultureInfo GetUserDefaultCulture() return CultureInfo.InvariantCulture; CultureInfo cultureInfo; - if (CultureData.GetDefaultLocaleName(out string? localeName)) + string? localeName; + bool result = false; +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + { + localeName = Interop.Globalization.GetDefaultLocaleNameNative(); + result = localeName != null; + } + else + { + result = CultureData.GetDefaultLocaleName(out localeName); + } +#else + result = CultureData.GetDefaultLocaleName(out localeName); +#endif + if (result) { Debug.Assert(localeName != null); cultureInfo = GetCultureByName(localeName); diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs index 41a0705698bc09..20e9b76b4e1e76 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs @@ -434,7 +434,18 @@ private static unsafe ushort [] InitOrdinalCasingPage(int pageNumber) fixed (ushort* table = casingTable) { char* pTable = (char*)table; +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + { + Interop.Globalization.InitOrdinalCasingPageNative(pageNumber, pTable); + } + else + { + Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); + } +#else Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); +#endif } Volatile.Write(ref s_casingTable[pageNumber], casingTable); return casingTable; diff --git a/src/native/libs/System.Globalization.Native/entrypoints.c b/src/native/libs/System.Globalization.Native/entrypoints.c index 1f345991505fa4..6aae94880f0a48 100644 --- a/src/native/libs/System.Globalization.Native/entrypoints.c +++ b/src/native/libs/System.Globalization.Native/entrypoints.c @@ -76,6 +76,7 @@ static const Entry s_globalizationNative[] = DllImportEntry(GlobalizationNative_GetLocaleTimeFormatNative) DllImportEntry(GlobalizationNative_GetTimeZoneDisplayNameNative) DllImportEntry(GlobalizationNative_IndexOfNative) + DllImportEntry(GlobalizationNative_InitOrdinalCasingPageNative) DllImportEntry(GlobalizationNative_IsNormalizedNative) DllImportEntry(GlobalizationNative_NormalizeStringNative) DllImportEntry(GlobalizationNative_StartsWithNative) diff --git a/src/native/libs/System.Globalization.Native/pal_casing.h b/src/native/libs/System.Globalization.Native/pal_casing.h index e39d38ecb1c119..4201adf3f06d83 100644 --- a/src/native/libs/System.Globalization.Native/pal_casing.h +++ b/src/native/libs/System.Globalization.Native/pal_casing.h @@ -38,4 +38,6 @@ PALEXPORT int32_t GlobalizationNative_ChangeCaseInvariantNative(const uint16_t* uint16_t* lpDst, int32_t cwDstLength, int32_t bToUpper); + +PALEXPORT void GlobalizationNative_InitOrdinalCasingPageNative(int32_t pageNumber, UChar* pTarget); #endif diff --git a/src/native/libs/System.Globalization.Native/pal_casing.m b/src/native/libs/System.Globalization.Native/pal_casing.m index 31fd647347daf1..5217ed6df940e9 100644 --- a/src/native/libs/System.Globalization.Native/pal_casing.m +++ b/src/native/libs/System.Globalization.Native/pal_casing.m @@ -149,4 +149,25 @@ int32_t GlobalizationNative_ChangeCaseInvariantNative(const uint16_t* lpSrc, int } } +void GlobalizationNative_InitOrdinalCasingPageNative(int32_t pageNumber, UChar* pTarget) +{ + @autoreleasepool + { + pageNumber <<= 8; + for (int i = 0; i < 256; i++) + { + // Unfortunately, to ensure one-to-one simple mapping we have to call u_toupper on every character. + // Using string casing ICU APIs cannot give such results even when using NULL locale to force root behavior. + pTarget[i] = (UChar) u_toupper((UChar32)(pageNumber + i)); + } + + if (pageNumber == 0x0100) + { + // Disable Turkish I behavior on Ordinal operations + pTarget[0x31] = (UChar)0x0131; // Turkish lowercase i + pTarget[0x7F] = (UChar)0x017F; // // 017F;LATIN SMALL LETTER LONG S + } + } +} + #endif diff --git a/src/native/libs/System.Globalization.Native/pal_locale.h b/src/native/libs/System.Globalization.Native/pal_locale.h index 4a1fe0768e4fda..d0fc81c071e9c9 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.h +++ b/src/native/libs/System.Globalization.Native/pal_locale.h @@ -18,9 +18,13 @@ PALEXPORT int32_t GlobalizationNative_GetLocaleTimeFormat(const UChar* localeNam int32_t valueLength); #ifdef __APPLE__ +PALEXPORT const char* GlobalizationNative_GetDefaultLocaleNameNative(void); + PALEXPORT const char* GlobalizationNative_GetLocaleNameNative(const char* localeName); PALEXPORT const char* GlobalizationNative_GetLocaleTimeFormatNative(const char* localeName, int shortFormat); PALEXPORT int32_t GlobalizationNative_GetLocalesNative(UChar* locales, int32_t length); + +PALEXPORT int32_t GlobalizationNative_IsPredefinedLocaleNative(const char* localeName); #endif diff --git a/src/native/libs/System.Globalization.Native/pal_locale.m b/src/native/libs/System.Globalization.Native/pal_locale.m index 4789ac89691da2..e3323e42f9bd0f 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.m +++ b/src/native/libs/System.Globalization.Native/pal_locale.m @@ -734,4 +734,49 @@ int32_t GlobalizationNative_GetLocalesNative(UChar* value, int32_t length) return strdup([dataPath UTF8String]); } } + +const char* GlobalizationNative_GetDefaultLocaleNameNative(void) +{ + @autoreleasepool + { + NSLocale *currentLocale = [NSLocale currentLocale]; + NSString *localeName = @""; + + if (!currentLocale) + { + return strdup([localeName UTF8String]); + } + + if ([currentLocale.languageCode length] > 0 && [currentLocale.countryCode length] > 0) + { + localeName = [NSString stringWithFormat:@"%@-%@", currentLocale.languageCode, currentLocale.countryCode]; + } + else + { + localeName = currentLocale.localeIdentifier; + } + + return strdup([localeName UTF8String]); + } +} + +// GlobalizationNative_IsPredefinedLocaleNative returns TRUE if localeName exists in availableLocaleIdentifiers. +// Otherwise it returns FALSE; + +int32_t GlobalizationNative_IsPredefinedLocaleNative(const char* localeName) +{ + @autoreleasepool + { + NSString *localeIdentifier = [NSString stringWithFormat:@"%s", localeName]; + NSString *desiredLocaleIdentifier = [localeIdentifier stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; + NSArray *availableLocales = [NSLocale availableLocaleIdentifiers]; + + if ([availableLocales containsObject:desiredLocaleIdentifier]) + { + return true; + } + + return false; + } +} #endif From 44cfd2c78fa9020714ada4827f9c274a09521c04 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Fri, 27 Oct 2023 15:15:54 +0200 Subject: [PATCH 2/8] Changes requested by review --- .../TestUtilities/System/PlatformDetection.cs | 2 +- .../tests/CompareInfo/CompareInfoTestsBase.cs | 2 +- .../src/System/Globalization/CultureData.Icu.cs | 7 +++++++ .../System/Globalization/CultureInfo.Unix.cs | 17 +---------------- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 3738c5aede333b..2a9c2909708208 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -374,7 +374,7 @@ public static string GetDistroVersionString() public static bool IsNotHybridGlobalizationOnOSX => !IsHybridGlobalizationOnOSX; public static bool IsIcuGlobalization => ICUVersion > new Version(0, 0, 0, 0); public static bool IsIcuGlobalizationAndNotHybridOnBrowser => IsIcuGlobalization && IsNotHybridGlobalizationOnBrowser; - public static bool IsIcuGlobalizationAndNotHybrid => IsIcuGlobalization && IsNotHybridGlobalizationOnBrowser && IsNotHybridGlobalizationOnOSX; + public static bool IsIcuGlobalizationAndNotHybrid => IsIcuGlobalization && IsNotHybridGlobalization; public static bool IsNlsGlobalization => IsNotInvariantGlobalization && !IsIcuGlobalization; public static bool IsSubstAvailable diff --git a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTestsBase.cs b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTestsBase.cs index d5310ba7cf5d68..3397b16e169189 100644 --- a/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTestsBase.cs +++ b/src/libraries/System.Globalization/tests/CompareInfo/CompareInfoTestsBase.cs @@ -45,6 +45,6 @@ protected static bool IsNotWindowsKanaRegressedVersion() => !PlatformDetection.I s_invariantCompare.Compare("\u3060", "\uFF80\uFF9E", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase) == 0; protected static bool IsNotWindowsKanaRegressedVersionAndNotHybridGlobalizationOnWasm() => !PlatformDetection.IsHybridGlobalizationOnBrowser && IsNotWindowsKanaRegressedVersion(); - protected static bool IsNotWindowsKanaRegressedVersionAndNotHybridGlobalization() => IsNotWindowsKanaRegressedVersionAndNotHybridGlobalizationOnWasm() && !PlatformDetection.IsHybridGlobalizationOnOSX; + protected static bool IsNotWindowsKanaRegressedVersionAndNotHybridGlobalization() => IsNotWindowsKanaRegressedVersion() && PlatformDetection.IsNotHybridGlobalization; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 97422b35bf96b6..6123878d034864 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -181,6 +181,13 @@ internal static unsafe bool GetLocaleName(string localeName, out string? windows internal static unsafe bool GetDefaultLocaleName([NotNullWhen(true)] out string? windowsName) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + { + windowsName = Interop.Globalization.GetDefaultLocaleNameNative(); + return windowsName != null && windowsName.Length > 0; + } +#endif // Get the default (system) locale name from ICU char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs index 361c218da20775..a35b88c220609f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Unix.cs @@ -13,22 +13,7 @@ internal static CultureInfo GetUserDefaultCulture() return CultureInfo.InvariantCulture; CultureInfo cultureInfo; - string? localeName; - bool result = false; -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - if (GlobalizationMode.Hybrid) - { - localeName = Interop.Globalization.GetDefaultLocaleNameNative(); - result = localeName != null; - } - else - { - result = CultureData.GetDefaultLocaleName(out localeName); - } -#else - result = CultureData.GetDefaultLocaleName(out localeName); -#endif - if (result) + if (CultureData.GetDefaultLocaleName(out string? localeName)) { Debug.Assert(localeName != null); cultureInfo = GetCultureByName(localeName); From 0ea3dbcebd992339a40aa1545229e2fccbc6e469 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Mon, 30 Oct 2023 13:28:21 +0100 Subject: [PATCH 3/8] Fix LocalD check and minor refactoring --- .../System/Globalization/CultureData.Icu.cs | 36 +++++++++---------- .../System/Globalization/OrdinalCasing.Icu.cs | 4 +-- .../System.Globalization.Native/pal_locale.m | 4 +-- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 6123878d034864..5a683c76df4c72 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -130,6 +130,7 @@ private bool InitIcuCultureDataCore() } } else +#endif { // Get the locale name from ICU if (!GetLocaleName(realNameBuffer, out _sWindowsName)) @@ -137,13 +138,6 @@ private bool InitIcuCultureDataCore() return false; } } -#else - // Get the locale name from ICU - if (!GetLocaleName(realNameBuffer, out _sWindowsName)) - { - return false; // fail - } -#endif Debug.Assert(_sWindowsName != null); @@ -187,18 +181,21 @@ internal static unsafe bool GetDefaultLocaleName([NotNullWhen(true)] out string? windowsName = Interop.Globalization.GetDefaultLocaleNameNative(); return windowsName != null && windowsName.Length > 0; } + else #endif - // Get the default (system) locale name from ICU - char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; - if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) - { - windowsName = null; - return false; // fail - } + { + // Get the default (system) locale name from ICU + char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; + if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) + { + windowsName = null; + return false; // fail + } - // Success - use the locale name returned which may be different than realNameBuffer (casing) - windowsName = new string(buffer); // the name passed to subsequent ICU calls - return true; + // Success - use the locale name returned which may be different than realNameBuffer (casing) + windowsName = new string(buffer); // the name passed to subsequent ICU calls + return true; + } } private string IcuGetLocaleInfo(LocaleStringData type, string? uiCultureName = null) @@ -318,8 +315,11 @@ internal static bool IcuIsEnsurePredefinedLocaleName(string name) { return Interop.Globalization.IsPredefinedLocaleNative(name); } + else + { #endif - return Interop.Globalization.IsPredefinedLocale(name); + return Interop.Globalization.IsPredefinedLocale(name); + } } private static string ConvertIcuTimeFormatString(ReadOnlySpan icuFormatString) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs index 20e9b76b4e1e76..6d6dfe01cbb0b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs @@ -440,12 +440,10 @@ private static unsafe ushort [] InitOrdinalCasingPage(int pageNumber) Interop.Globalization.InitOrdinalCasingPageNative(pageNumber, pTable); } else +#endif { Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); } -#else - Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); -#endif } Volatile.Write(ref s_casingTable[pageNumber], casingTable); return casingTable; diff --git a/src/native/libs/System.Globalization.Native/pal_locale.m b/src/native/libs/System.Globalization.Native/pal_locale.m index a338621afdd234..fce8f03a4fc704 100644 --- a/src/native/libs/System.Globalization.Native/pal_locale.m +++ b/src/native/libs/System.Globalization.Native/pal_locale.m @@ -810,10 +810,10 @@ int32_t GlobalizationNative_IsPredefinedLocaleNative(const char* localeName) @autoreleasepool { NSString *localeIdentifier = [NSString stringWithFormat:@"%s", localeName]; - NSString *desiredLocaleIdentifier = [localeIdentifier stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; + NSString *localeIdentifierByRegionDesignator = [localeIdentifier stringByReplacingOccurrencesOfString:@"-" withString:@"_"]; NSArray *availableLocales = [NSLocale availableLocaleIdentifiers]; - if ([availableLocales containsObject:desiredLocaleIdentifier]) + if ([availableLocales containsObject:localeIdentifier] || [availableLocales containsObject:localeIdentifierByRegionDesignator]) { return true; } From b3d7bd0c93b4e5c0b4afd891a06acbc64d774fe3 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Mon, 30 Oct 2023 13:31:52 +0100 Subject: [PATCH 4/8] Fix spacing --- .../src/System/Globalization/CultureData.Icu.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 5a683c76df4c72..4eb9263fba7196 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -183,7 +183,7 @@ internal static unsafe bool GetDefaultLocaleName([NotNullWhen(true)] out string? } else #endif - { + { // Get the default (system) locale name from ICU char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) @@ -195,7 +195,7 @@ internal static unsafe bool GetDefaultLocaleName([NotNullWhen(true)] out string? // Success - use the locale name returned which may be different than realNameBuffer (casing) windowsName = new string(buffer); // the name passed to subsequent ICU calls return true; - } + } } private string IcuGetLocaleInfo(LocaleStringData type, string? uiCultureName = null) From 42ff127998d433330de60441852800fda7054ab1 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Mon, 30 Oct 2023 14:33:35 +0100 Subject: [PATCH 5/8] Fix build failure --- .../System/Globalization/CultureData.Icu.cs | 34 +++++++++---------- .../System/Globalization/OrdinalCasing.Icu.cs | 4 ++- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 4eb9263fba7196..6123878d034864 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -130,7 +130,6 @@ private bool InitIcuCultureDataCore() } } else -#endif { // Get the locale name from ICU if (!GetLocaleName(realNameBuffer, out _sWindowsName)) @@ -138,6 +137,13 @@ private bool InitIcuCultureDataCore() return false; } } +#else + // Get the locale name from ICU + if (!GetLocaleName(realNameBuffer, out _sWindowsName)) + { + return false; // fail + } +#endif Debug.Assert(_sWindowsName != null); @@ -181,21 +187,18 @@ internal static unsafe bool GetDefaultLocaleName([NotNullWhen(true)] out string? windowsName = Interop.Globalization.GetDefaultLocaleNameNative(); return windowsName != null && windowsName.Length > 0; } - else #endif + // Get the default (system) locale name from ICU + char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; + if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) { - // Get the default (system) locale name from ICU - char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; - if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) - { - windowsName = null; - return false; // fail - } - - // Success - use the locale name returned which may be different than realNameBuffer (casing) - windowsName = new string(buffer); // the name passed to subsequent ICU calls - return true; + windowsName = null; + return false; // fail } + + // Success - use the locale name returned which may be different than realNameBuffer (casing) + windowsName = new string(buffer); // the name passed to subsequent ICU calls + return true; } private string IcuGetLocaleInfo(LocaleStringData type, string? uiCultureName = null) @@ -315,11 +318,8 @@ internal static bool IcuIsEnsurePredefinedLocaleName(string name) { return Interop.Globalization.IsPredefinedLocaleNative(name); } - else - { #endif - return Interop.Globalization.IsPredefinedLocale(name); - } + return Interop.Globalization.IsPredefinedLocale(name); } private static string ConvertIcuTimeFormatString(ReadOnlySpan icuFormatString) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs index 6d6dfe01cbb0b1..20e9b76b4e1e76 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs @@ -440,10 +440,12 @@ private static unsafe ushort [] InitOrdinalCasingPage(int pageNumber) Interop.Globalization.InitOrdinalCasingPageNative(pageNumber, pTable); } else -#endif { Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); } +#else + Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); +#endif } Volatile.Write(ref s_casingTable[pageNumber], casingTable); return casingTable; From 2414ce9dfbfb245e777c0b9d2bd1644ad84d5f5e Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Mon, 30 Oct 2023 15:18:32 +0100 Subject: [PATCH 6/8] Remove duplicates --- .../System/Globalization/CultureData.Icu.cs | 34 +++++++++---------- .../System/Globalization/OrdinalCasing.Icu.cs | 4 +-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs index 6123878d034864..add21d8ce3f4d6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Icu.cs @@ -130,6 +130,7 @@ private bool InitIcuCultureDataCore() } } else +#endif { // Get the locale name from ICU if (!GetLocaleName(realNameBuffer, out _sWindowsName)) @@ -137,13 +138,6 @@ private bool InitIcuCultureDataCore() return false; } } -#else - // Get the locale name from ICU - if (!GetLocaleName(realNameBuffer, out _sWindowsName)) - { - return false; // fail - } -#endif Debug.Assert(_sWindowsName != null); @@ -187,18 +181,21 @@ internal static unsafe bool GetDefaultLocaleName([NotNullWhen(true)] out string? windowsName = Interop.Globalization.GetDefaultLocaleNameNative(); return windowsName != null && windowsName.Length > 0; } + else #endif - // Get the default (system) locale name from ICU - char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; - if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) { - windowsName = null; - return false; // fail - } + // Get the default (system) locale name from ICU + char* buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; + if (!Interop.Globalization.GetDefaultLocaleName(buffer, ICU_ULOC_FULLNAME_CAPACITY)) + { + windowsName = null; + return false; // fail + } - // Success - use the locale name returned which may be different than realNameBuffer (casing) - windowsName = new string(buffer); // the name passed to subsequent ICU calls - return true; + // Success - use the locale name returned which may be different than realNameBuffer (casing) + windowsName = new string(buffer); // the name passed to subsequent ICU calls + return true; + } } private string IcuGetLocaleInfo(LocaleStringData type, string? uiCultureName = null) @@ -318,8 +315,11 @@ internal static bool IcuIsEnsurePredefinedLocaleName(string name) { return Interop.Globalization.IsPredefinedLocaleNative(name); } + else #endif - return Interop.Globalization.IsPredefinedLocale(name); + { + return Interop.Globalization.IsPredefinedLocale(name); + } } private static string ConvertIcuTimeFormatString(ReadOnlySpan icuFormatString) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs index 20e9b76b4e1e76..6d6dfe01cbb0b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs @@ -440,12 +440,10 @@ private static unsafe ushort [] InitOrdinalCasingPage(int pageNumber) Interop.Globalization.InitOrdinalCasingPageNative(pageNumber, pTable); } else +#endif { Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); } -#else - Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); -#endif } Volatile.Write(ref s_casingTable[pageNumber], casingTable); return casingTable; From c7c9adea117aca05914c364f1942b6abc4a7ae7e Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 31 Oct 2023 17:24:38 +0100 Subject: [PATCH 7/8] Remove duplicate by moving code to pal_common.c --- .../Common/src/Interop/Interop.Casing.iOS.cs | 3 --- .../System/Globalization/OrdinalCasing.Icu.cs | 11 +--------- src/mono/mono/mini/CMakeLists.txt | 1 + .../CMakeLists.txt | 1 + .../System.Globalization.Native/entrypoints.c | 1 - .../System.Globalization.Native/pal_casing.c | 18 ---------------- .../System.Globalization.Native/pal_casing.h | 2 -- .../System.Globalization.Native/pal_casing.m | 21 ------------------- .../System.Globalization.Native/pal_common.c | 20 ++++++++++++++++++ 9 files changed, 23 insertions(+), 55 deletions(-) create mode 100644 src/native/libs/System.Globalization.Native/pal_common.c diff --git a/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs b/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs index 19372c62907453..5e0140faa4c43e 100644 --- a/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs +++ b/src/libraries/Common/src/Interop/Interop.Casing.iOS.cs @@ -12,8 +12,5 @@ internal static partial class Globalization [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_ChangeCaseInvariantNative", StringMarshalling = StringMarshalling.Utf8)] internal static unsafe partial int ChangeCaseInvariantNative(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, [MarshalAs(UnmanagedType.Bool)] bool bToUpper); - - [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_InitOrdinalCasingPageNative", StringMarshalling = StringMarshalling.Utf16)] - internal static unsafe partial void InitOrdinalCasingPageNative(int pageNumber, char* pTarget); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs index 6d6dfe01cbb0b1..41a0705698bc09 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs @@ -434,16 +434,7 @@ private static unsafe ushort [] InitOrdinalCasingPage(int pageNumber) fixed (ushort* table = casingTable) { char* pTable = (char*)table; -#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS - if (GlobalizationMode.Hybrid) - { - Interop.Globalization.InitOrdinalCasingPageNative(pageNumber, pTable); - } - else -#endif - { - Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); - } + Interop.Globalization.InitOrdinalCasingPage(pageNumber, pTable); } Volatile.Write(ref s_casingTable[pageNumber], casingTable); return casingTable; diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 98537044e3e633..931fb3ab154271 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -60,6 +60,7 @@ if(HAVE_SYS_ICU) pal_calendarData.c pal_casing.c pal_collation.c + pal_common.c pal_idna.c pal_locale.c pal_localeNumberData.c diff --git a/src/native/libs/System.Globalization.Native/CMakeLists.txt b/src/native/libs/System.Globalization.Native/CMakeLists.txt index 3996d9bb7e5842..6e4dee71fe6810 100644 --- a/src/native/libs/System.Globalization.Native/CMakeLists.txt +++ b/src/native/libs/System.Globalization.Native/CMakeLists.txt @@ -60,6 +60,7 @@ set(NATIVEGLOBALIZATION_SOURCES pal_calendarData.c pal_casing.c pal_collation.c + pal_common.c pal_idna.c pal_locale.c pal_localeNumberData.c diff --git a/src/native/libs/System.Globalization.Native/entrypoints.c b/src/native/libs/System.Globalization.Native/entrypoints.c index 6aae94880f0a48..1f345991505fa4 100644 --- a/src/native/libs/System.Globalization.Native/entrypoints.c +++ b/src/native/libs/System.Globalization.Native/entrypoints.c @@ -76,7 +76,6 @@ static const Entry s_globalizationNative[] = DllImportEntry(GlobalizationNative_GetLocaleTimeFormatNative) DllImportEntry(GlobalizationNative_GetTimeZoneDisplayNameNative) DllImportEntry(GlobalizationNative_IndexOfNative) - DllImportEntry(GlobalizationNative_InitOrdinalCasingPageNative) DllImportEntry(GlobalizationNative_IsNormalizedNative) DllImportEntry(GlobalizationNative_NormalizeStringNative) DllImportEntry(GlobalizationNative_StartsWithNative) diff --git a/src/native/libs/System.Globalization.Native/pal_casing.c b/src/native/libs/System.Globalization.Native/pal_casing.c index aad75f64da7d9b..52c8986c76d1d2 100644 --- a/src/native/libs/System.Globalization.Native/pal_casing.c +++ b/src/native/libs/System.Globalization.Native/pal_casing.c @@ -151,24 +151,6 @@ void GlobalizationNative_ChangeCaseTurkish( } } -void GlobalizationNative_InitOrdinalCasingPage(int32_t pageNumber, UChar* pTarget) -{ - pageNumber <<= 8; - for (int i = 0; i < 256; i++) - { - // Unfortunately, to ensure one-to-one simple mapping we have to call u_toupper on every character. - // Using string casing ICU APIs cannot give such results even when using NULL locale to force root behavior. - pTarget[i] = (UChar) u_toupper((UChar32)(pageNumber + i)); - } - - if (pageNumber == 0x0100) - { - // Disable Turkish I behavior on Ordinal operations - pTarget[0x31] = (UChar)0x0131; // Turkish lowercase i - pTarget[0x7F] = (UChar)0x017F; // // 017F;LATIN SMALL LETTER LONG S - } -} - #ifdef __clang__ #pragma clang diagnostic pop #endif diff --git a/src/native/libs/System.Globalization.Native/pal_casing.h b/src/native/libs/System.Globalization.Native/pal_casing.h index 4201adf3f06d83..e39d38ecb1c119 100644 --- a/src/native/libs/System.Globalization.Native/pal_casing.h +++ b/src/native/libs/System.Globalization.Native/pal_casing.h @@ -38,6 +38,4 @@ PALEXPORT int32_t GlobalizationNative_ChangeCaseInvariantNative(const uint16_t* uint16_t* lpDst, int32_t cwDstLength, int32_t bToUpper); - -PALEXPORT void GlobalizationNative_InitOrdinalCasingPageNative(int32_t pageNumber, UChar* pTarget); #endif diff --git a/src/native/libs/System.Globalization.Native/pal_casing.m b/src/native/libs/System.Globalization.Native/pal_casing.m index 5217ed6df940e9..31fd647347daf1 100644 --- a/src/native/libs/System.Globalization.Native/pal_casing.m +++ b/src/native/libs/System.Globalization.Native/pal_casing.m @@ -149,25 +149,4 @@ int32_t GlobalizationNative_ChangeCaseInvariantNative(const uint16_t* lpSrc, int } } -void GlobalizationNative_InitOrdinalCasingPageNative(int32_t pageNumber, UChar* pTarget) -{ - @autoreleasepool - { - pageNumber <<= 8; - for (int i = 0; i < 256; i++) - { - // Unfortunately, to ensure one-to-one simple mapping we have to call u_toupper on every character. - // Using string casing ICU APIs cannot give such results even when using NULL locale to force root behavior. - pTarget[i] = (UChar) u_toupper((UChar32)(pageNumber + i)); - } - - if (pageNumber == 0x0100) - { - // Disable Turkish I behavior on Ordinal operations - pTarget[0x31] = (UChar)0x0131; // Turkish lowercase i - pTarget[0x7F] = (UChar)0x017F; // // 017F;LATIN SMALL LETTER LONG S - } - } -} - #endif diff --git a/src/native/libs/System.Globalization.Native/pal_common.c b/src/native/libs/System.Globalization.Native/pal_common.c new file mode 100644 index 00000000000000..afb2f8d79b4f79 --- /dev/null +++ b/src/native/libs/System.Globalization.Native/pal_common.c @@ -0,0 +1,20 @@ +#include "pal_icushim_internal.h" +#include "pal_casing.h" + +void GlobalizationNative_InitOrdinalCasingPage(int32_t pageNumber, UChar* pTarget) +{ + pageNumber <<= 8; + for (int i = 0; i < 256; i++) + { + // Unfortunately, to ensure one-to-one simple mapping we have to call u_toupper on every character. + // Using string casing ICU APIs cannot give such results even when using NULL locale to force root behavior. + pTarget[i] = (UChar) u_toupper((UChar32)(pageNumber + i)); + } + + if (pageNumber == 0x0100) + { + // Disable Turkish I behavior on Ordinal operations + pTarget[0x31] = (UChar)0x0131; // Turkish lowercase i + pTarget[0x7F] = (UChar)0x017F; // // 017F;LATIN SMALL LETTER LONG S + } +} From daed1f570ee53522d5231abde63614bfb22d359c Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 31 Oct 2023 17:53:10 +0100 Subject: [PATCH 8/8] Fix android build --- src/native/libs/System.Globalization.Native/pal_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/libs/System.Globalization.Native/pal_common.c b/src/native/libs/System.Globalization.Native/pal_common.c index afb2f8d79b4f79..5904a1c3bdbe25 100644 --- a/src/native/libs/System.Globalization.Native/pal_common.c +++ b/src/native/libs/System.Globalization.Native/pal_common.c @@ -1,3 +1,4 @@ +#include #include "pal_icushim_internal.h" #include "pal_casing.h"