From 67b1ede8cb7758b9c54bfce050c9c4b15715c6bc Mon Sep 17 00:00:00 2001
From: Meri Khamoyan <96171496+mkhamoyan@users.noreply.github.com>
Date: Thu, 29 Jun 2023 12:23:59 +0400
Subject: [PATCH] [OSX] HybridGlobalization Implement casing functions (#87919)
Implement GlobalizationNative_ChangeCaseNative , GlobalizationNative_ChangeCaseInvariantNative for OSX
---
.../features/globalization-hybrid-mode.md | 32 +++++-
.../Common/src/Interop/Interop.Casing.OSX.cs | 16 +++
.../Common/src/Interop/Interop.ResultCode.cs | 3 +-
.../System.Globalization.IOS.Tests.csproj | 1 +
.../System/Globalization/TextInfoTests.cs | 44 ++++----
.../System.Private.CoreLib.Shared.projitems | 4 +
.../src/System/Globalization/TextInfo.OSX.cs | 27 +++++
.../src/System/Globalization/TextInfo.cs | 6 +
src/mono/mono/mini/CMakeLists.txt | 3 +-
.../CMakeLists.txt | 2 +-
.../System.Globalization.Native/entrypoints.c | 8 +-
.../System.Globalization.Native/pal_casing.h | 16 +++
.../System.Globalization.Native/pal_casing.m | 103 ++++++++++++++++++
.../System.Globalization.Native/pal_errors.h | 3 +-
.../System.Globalization.Native/pal_locale.m | 2 +-
15 files changed, 242 insertions(+), 28 deletions(-)
create mode 100644 src/libraries/Common/src/Interop/Interop.Casing.OSX.cs
create mode 100644 src/libraries/System.Private.CoreLib/src/System/Globalization/TextInfo.OSX.cs
create mode 100644 src/native/libs/System.Globalization.Native/pal_casing.m
diff --git a/docs/design/features/globalization-hybrid-mode.md b/docs/design/features/globalization-hybrid-mode.md
index 8b0be8251e5..920f808b4e6 100644
--- a/docs/design/features/globalization-hybrid-mode.md
+++ b/docs/design/features/globalization-hybrid-mode.md
@@ -408,4 +408,34 @@ Affected public APIs:
- CompareInfo.GetSortKeyLength
- CompareInfo.GetHashCode
-Apple Native API does not have an equivalent, so they throw `PlatformNotSupportedException`.
\ No newline at end of file
+Apple Native API does not have an equivalent, so they throw `PlatformNotSupportedException`.
+
+
+## Case change
+
+Affected public APIs:
+- TextInfo.ToLower,
+- TextInfo.ToUpper
+
+Below function are used from apple native functions:
+- [uppercaseString](https://developer.apple.com/documentation/foundation/nsstring/1409855-uppercasestring)
+- [lowercaseString](https://developer.apple.com/documentation/foundation/nsstring/1408467-lowercasestring)
+- [uppercaseStringWithLocale](https://developer.apple.com/documentation/foundation/nsstring/1413316-uppercasestringwithlocale?language=objc)
+- [lowercaseStringWithLocale](https://developer.apple.com/documentation/foundation/nsstring/1417298-lowercasestringwithlocale?language=objc)
+
+Behavioural changes compared to ICU
+
+ - Final sigma behavior correction:
+
+ ICU-based case change does not respect final-sigma rule, but hybrid does, so "ΒΌΛΟΣ" -> "βόλος", not "βόλοσ".
+
+ - Below cases will throw exception because of insufficiently sized destination buffer
+
+ - Capitalizing the German letter ß (sharp S) gives SS when using Apple native functions.
+
+ - Capitalizing ligatures gives different result on Apple platforms, eg. "\uFB00" (ff) uppercase (FF)
+
+ - Capitalizing "\u0149" (ʼn) on Apple platforms returns combination of "\u02BC" (ʼ) and N -> (ʼN)
+
+
+
diff --git a/src/libraries/Common/src/Interop/Interop.Casing.OSX.cs b/src/libraries/Common/src/Interop/Interop.Casing.OSX.cs
new file mode 100644
index 00000000000..5e0140faa4c
--- /dev/null
+++ b/src/libraries/Common/src/Interop/Interop.Casing.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.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Globalization
+ {
+ [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_ChangeCaseNative", StringMarshalling = StringMarshalling.Utf16)]
+ internal static unsafe partial int ChangeCaseNative(string localeName, int lNameLen, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, [MarshalAs(UnmanagedType.Bool)] bool bToUpper);
+
+ [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);
+ }
+}
diff --git a/src/libraries/Common/src/Interop/Interop.ResultCode.cs b/src/libraries/Common/src/Interop/Interop.ResultCode.cs
index b99787f061f..c55bba661fc 100644
--- a/src/libraries/Common/src/Interop/Interop.ResultCode.cs
+++ b/src/libraries/Common/src/Interop/Interop.ResultCode.cs
@@ -11,7 +11,8 @@ internal enum ResultCode
Success = 0,
UnknownError = 1,
InsufficientBuffer = 2,
- OutOfMemory = 3
+ OutOfMemory = 3,
+ InvalidCodePoint = 4,
}
}
}
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 1c680de3e24..da9a1a79c18 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
@@ -38,5 +38,6 @@
+
diff --git a/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs b/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs
index fcc4c53f5e4..6426a2a427b 100644
--- a/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs
+++ b/src/libraries/System.Globalization/tests/System/Globalization/TextInfoTests.cs
@@ -274,9 +274,9 @@ public static IEnumerable