From cb5ca7c96734a6d4f058c304f98c27149466ca09 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 15 Aug 2023 10:37:19 +0200 Subject: [PATCH 1/4] Implement native normalization functions --- .../src/Interop/Interop.Normalization.iOS.cs | 17 +++ ....Globalization.Extensions.iOS.Tests.csproj | 19 ++++ .../tests/Normalization/NormalizationAll.cs | 2 +- .../Normalization/StringNormalizationTests.cs | 2 +- .../System.Private.CoreLib.Shared.projitems | 3 + .../System/Globalization/Normalization.Icu.cs | 15 ++- .../src/System/Globalization/Normalization.cs | 12 ++ src/mono/mono/mini/CMakeLists.txt | 3 +- .../CMakeLists.txt | 4 +- .../System.Globalization.Native/entrypoints.c | 2 + .../pal_normalization.h | 12 ++ .../pal_normalization.m | 106 ++++++++++++++++++ 12 files changed, 191 insertions(+), 6 deletions(-) create mode 100644 src/libraries/Common/src/Interop/Interop.Normalization.iOS.cs create mode 100644 src/libraries/System.Globalization.Extensions/tests/Hybrid/System.Globalization.Extensions.iOS.Tests.csproj create mode 100644 src/native/libs/System.Globalization.Native/pal_normalization.m diff --git a/src/libraries/Common/src/Interop/Interop.Normalization.iOS.cs b/src/libraries/Common/src/Interop/Interop.Normalization.iOS.cs new file mode 100644 index 00000000000000..4ba97148b45389 --- /dev/null +++ b/src/libraries/Common/src/Interop/Interop.Normalization.iOS.cs @@ -0,0 +1,17 @@ +// 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; +using System.Text; + +internal static partial class Interop +{ + internal static partial class Globalization + { + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_IsNormalizedNative", StringMarshalling = StringMarshalling.Utf16)] + internal static unsafe partial int IsNormalizedNative(NormalizationForm normalizationForm, char* src, int srcLen); + + [LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_NormalizeStringNative", StringMarshalling = StringMarshalling.Utf16)] + internal static unsafe partial int NormalizeStringNative(NormalizationForm normalizationForm, char* src, int srcLen, char* buffer, int bufferLength); + } +} diff --git a/src/libraries/System.Globalization.Extensions/tests/Hybrid/System.Globalization.Extensions.iOS.Tests.csproj b/src/libraries/System.Globalization.Extensions/tests/Hybrid/System.Globalization.Extensions.iOS.Tests.csproj new file mode 100644 index 00000000000000..ada1f18597f6ed --- /dev/null +++ b/src/libraries/System.Globalization.Extensions/tests/Hybrid/System.Globalization.Extensions.iOS.Tests.csproj @@ -0,0 +1,19 @@ + + + $(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-maccatalyst + true + true + + + + + + + + NormalizationDataWin8 + + + NormalizationDataWin7 + + + diff --git a/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs b/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs index 48f73a4527a389..8d27652096c51b 100644 --- a/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs +++ b/src/libraries/System.Globalization.Extensions/tests/Normalization/NormalizationAll.cs @@ -52,7 +52,7 @@ public void Normalize() VerifyConformanceInvariant(NormalizationForm.FormD, part0, part1, part2, part3, part4); // Mobile / Browser ICU doesn't support FormKC and FormKD - if (PlatformDetection.IsNotUsingLimitedCultures) + if (PlatformDetection.IsNotUsingLimitedCultures || PlatformDetection.IsHybridGlobalizationOnOSX) { // Form KC VerifyConformanceInvariant(NormalizationForm.FormKC, part0, part1, part2, part3, part4); diff --git a/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs b/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs index 7fe18bb314049f..252d19a16f17b8 100644 --- a/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs +++ b/src/libraries/System.Globalization.Extensions/tests/Normalization/StringNormalizationTests.cs @@ -49,7 +49,7 @@ public static IEnumerable NormalizeTestData() yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormC, "\u1E9b\u0323" }; yield return new object[] { "\u1E9b\u0323", NormalizationForm.FormD, "\u017f\u0323\u0307" }; - if (PlatformDetection.IsNotUsingLimitedCultures) + if (PlatformDetection.IsNotUsingLimitedCultures || PlatformDetection.IsHybridGlobalizationOnOSX) { // Mobile / Browser ICU doesn't support FormKC and FormKD yield return new object[] { "\uFB01", NormalizationForm.FormKC, "fi" }; 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 26d78479c72d8a..ca4c4c804fe5a2 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 @@ -1329,6 +1329,9 @@ Common\Interop\Interop.Normalization.cs + + Common\Interop\Interop.Normalization.iOS.cs + Common\Interop\Interop.ResultCode.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.Icu.cs index cfe698fabcd980..c23a0cdae59f1f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.Icu.cs @@ -20,7 +20,14 @@ private static unsafe bool IcuIsNormalized(string strInput, NormalizationForm no int ret; fixed (char* pInput = strInput) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + ret = Interop.Globalization.IsNormalizedNative(normalizationForm, pInput, strInput.Length); + else + ret = Interop.Globalization.IsNormalized(normalizationForm, pInput, strInput.Length); +#else ret = Interop.Globalization.IsNormalized(normalizationForm, pInput, strInput.Length); +#endif } if (ret == -1) @@ -53,7 +60,14 @@ private static unsafe string IcuNormalize(string strInput, NormalizationForm nor fixed (char* pInput = strInput) fixed (char* pDest = &MemoryMarshal.GetReference(buffer)) { +#if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS + if (GlobalizationMode.Hybrid) + realLen = Interop.Globalization.NormalizeStringNative(normalizationForm, pInput, strInput.Length, pDest, buffer.Length); + else + realLen = Interop.Globalization.NormalizeString(normalizationForm, pInput, strInput.Length, pDest, buffer.Length); +#else realLen = Interop.Globalization.NormalizeString(normalizationForm, pInput, strInput.Length, pDest, buffer.Length); +#endif } if (realLen == -1) @@ -100,7 +114,6 @@ private static void ValidateArguments(string strInput, NormalizationForm normali { Debug.Assert(strInput != null); - if (OperatingSystem.IsBrowser() && (normalizationForm == NormalizationForm.FormKC || normalizationForm == NormalizationForm.FormKD)) { // Browser's ICU doesn't contain data needed for FormKC and FormKD diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs index d120302a8aa8e7..3d1dec985320a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs @@ -19,7 +19,13 @@ internal static bool IsNormalized(string strInput, NormalizationForm normalizati return GlobalizationMode.UseNls ? NlsIsNormalized(strInput, normalizationForm) : +// #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS +// GlobalizationMode.Hybrid ? +// NativeIsNormalized(strInput, normalizationForm) : +// IcuIsNormalized(strInput, normalizationForm); +// #else IcuIsNormalized(strInput, normalizationForm); +// #endif } internal static string Normalize(string strInput, NormalizationForm normalizationForm) @@ -33,7 +39,13 @@ internal static string Normalize(string strInput, NormalizationForm normalizatio return GlobalizationMode.UseNls ? NlsNormalize(strInput, normalizationForm) : +// #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS +// GlobalizationMode.Hybrid ? +// NativeNormalize(strInput, normalizationForm) : +// IcuNormalize(strInput, normalizationForm); +// #else IcuNormalize(strInput, normalizationForm); +// #endif } } } diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt index 4ed9d8bfba781b..d87b0f15ef4a1f 100644 --- a/src/mono/mono/mini/CMakeLists.txt +++ b/src/mono/mono/mini/CMakeLists.txt @@ -74,7 +74,8 @@ if(HAVE_SYS_ICU) pal_locale.m pal_collation.m pal_casing.m - pal_calendarData.m) + pal_calendarData.m + pal_normalization.m) addprefix(icu_shim_darwin_sources "${ICU_SHIM_PATH}" "${icu_shim_darwin_sources_base}") set(icu_shim_sources ${icu_shim_sources} ${icu_shim_darwin_sources}) diff --git a/src/native/libs/System.Globalization.Native/CMakeLists.txt b/src/native/libs/System.Globalization.Native/CMakeLists.txt index 83ec10d583ee40..d7114d44b514f5 100644 --- a/src/native/libs/System.Globalization.Native/CMakeLists.txt +++ b/src/native/libs/System.Globalization.Native/CMakeLists.txt @@ -93,8 +93,8 @@ else() endif() if (CLR_CMAKE_TARGET_APPLE) - set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_locale.m pal_collation.m pal_casing.m pal_calendarData.m) - set_source_files_properties(pal_locale.m pal_collation.m pal_casing.m pal_calendarData.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}") + set(NATIVEGLOBALIZATION_SOURCES ${NATIVEGLOBALIZATION_SOURCES} pal_locale.m pal_collation.m pal_casing.m pal_calendarData.m pal_normalization.m) + set_source_files_properties(pal_locale.m pal_collation.m pal_casing.m pal_calendarData.m pal_normalization.m PROPERTIES COMPILE_FLAGS "${CLR_CMAKE_COMMON_OBJC_FLAGS}") 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/entrypoints.c b/src/native/libs/System.Globalization.Native/entrypoints.c index cffad72a023721..11ab93883cb0d9 100644 --- a/src/native/libs/System.Globalization.Native/entrypoints.c +++ b/src/native/libs/System.Globalization.Native/entrypoints.c @@ -71,6 +71,8 @@ static const Entry s_globalizationNative[] = DllImportEntry(GlobalizationNative_GetLocaleNameNative) DllImportEntry(GlobalizationNative_GetLocaleTimeFormatNative) DllImportEntry(GlobalizationNative_IndexOfNative) + DllImportEntry(GlobalizationNative_IsNormalizedNative) + DllImportEntry(GlobalizationNative_NormalizeStringNative) DllImportEntry(GlobalizationNative_StartsWithNative) #endif }; diff --git a/src/native/libs/System.Globalization.Native/pal_normalization.h b/src/native/libs/System.Globalization.Native/pal_normalization.h index b4c319f6770bd8..198d3f9d518f02 100644 --- a/src/native/libs/System.Globalization.Native/pal_normalization.h +++ b/src/native/libs/System.Globalization.Native/pal_normalization.h @@ -27,3 +27,15 @@ PALEXPORT int32_t GlobalizationNative_NormalizeString(NormalizationForm normaliz int32_t cwSrcLength, UChar* lpDst, int32_t cwDstLength); + +#ifdef __APPLE__ +PALEXPORT int32_t GlobalizationNative_IsNormalizedNative(NormalizationForm normalizationForm, + const uint16_t* lpStr, + int32_t cwStrLength); + +PALEXPORT int32_t GlobalizationNative_NormalizeStringNative(NormalizationForm normalizationForm, + const uint16_t* lpSource, + int32_t cwSourceLength, + uint16_t* lpDst, + int32_t cwDstLength); +#endif diff --git a/src/native/libs/System.Globalization.Native/pal_normalization.m b/src/native/libs/System.Globalization.Native/pal_normalization.m new file mode 100644 index 00000000000000..b3073747c65e1f --- /dev/null +++ b/src/native/libs/System.Globalization.Native/pal_normalization.m @@ -0,0 +1,106 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +#include "pal_errors.h" +#include "pal_icushim_internal.h" +#include "pal_normalization.h" +#import + +static NSString* GetNormalizedStringForForm(NormalizationForm normalizationForm, NSString* sourceString) +{ + switch (normalizationForm) + { + case FormC: + return sourceString.precomposedStringWithCanonicalMapping; + case FormD: + return sourceString.decomposedStringWithCanonicalMapping; + case FormKC: + return sourceString.precomposedStringWithCompatibilityMapping; + case FormKD: + return sourceString.decomposedStringWithCompatibilityMapping; + default: + return NULL; + } +} + +/* +Function: +IsNormalized + +Used by System.StringNormalizationExtensions.IsNormalized to detect if a string +is in a certain +Unicode Normalization Form. + +Return values: +0: lpStr is not normalized. +1: lpStr is normalized. +-1: internal error during normalization. +*/ +int32_t GlobalizationNative_IsNormalizedNative(NormalizationForm normalizationForm, const uint16_t* lpStr, int32_t cwStrLength) +{ + NSString *sourceString = [NSString stringWithCharacters: lpStr length: cwStrLength]; + NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); + + return normalizedString == NULL ? -1 : [sourceString isEqualToString: normalizedString]; +} + +/** + * Append a code point to a string, overwriting 1 or 2 code units. + * The offset points to the current end of the string contents + * and is advanced (post-increment). + * "Safe" macro, checks for a valid code point. + * Converts code points outside of Basic Multilingual Plane into + * corresponding surrogate pairs if sufficient space in the string. + * High surrogate range: 0xD800 - 0xDBFF + * Low surrogate range: 0xDC00 - 0xDFFF + * If the code point is not valid or a trail surrogate does not fit, + * then isError is set to true. + * + * @param buffer const uint16_t * string buffer + * @param offset string offset, must be offset= (capacity)) /* insufficiently sized destination buffer */ { \ + (isError) = InsufficientBuffer; \ + } else if ((uint32_t)(codePoint) > 0x10ffff) /* invalid code point */ { \ + (isError) = InvalidCodePoint; \ + } else if ((uint32_t)(codePoint) <= 0xffff) { \ + (buffer)[(offset)++] = (uint16_t)(codePoint); \ + } else { \ + (buffer)[(offset)++] = (uint16_t)(((codePoint) >> 10) + 0xd7c0); \ + (buffer)[(offset)++] = (uint16_t)(((codePoint)&0x3ff) | 0xdc00); \ + } \ +} + +/* +Function: +NormalizeString + +Used by System.StringNormalizationExtensions.Normalize to normalize a string +into a certain +Unicode Normalization Form. + +Return values: +0: internal error during normalization. +>0: the length of the normalized string (not counting the null terminator). +*/ +int32_t GlobalizationNative_NormalizeStringNative(NormalizationForm normalizationForm, const uint16_t* lpSource, int32_t cwSourceLength, uint16_t* lpDst, int32_t cwDstLength) +{ + NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; + NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); + int32_t index = 0; + int32_t dstIdx = 0, isError = 0; + uint16_t dstCodepoint; + while (index < normalizedString.length && dstIdx < cwDstLength) + { + dstCodepoint = [normalizedString characterAtIndex: index]; + Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError); + index++; + } + + return isError || normalizedString == NULL ? 0 : [normalizedString length]; +} From 7231959c3044e127a39df316ec0596c90c6b0128 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Tue, 15 Aug 2023 11:17:23 +0200 Subject: [PATCH 2/4] Remove commented lines --- .../src/System/Globalization/Normalization.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs index 3d1dec985320a7..d120302a8aa8e7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs @@ -19,13 +19,7 @@ internal static bool IsNormalized(string strInput, NormalizationForm normalizati return GlobalizationMode.UseNls ? NlsIsNormalized(strInput, normalizationForm) : -// #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS -// GlobalizationMode.Hybrid ? -// NativeIsNormalized(strInput, normalizationForm) : -// IcuIsNormalized(strInput, normalizationForm); -// #else IcuIsNormalized(strInput, normalizationForm); -// #endif } internal static string Normalize(string strInput, NormalizationForm normalizationForm) @@ -39,13 +33,7 @@ internal static string Normalize(string strInput, NormalizationForm normalizatio return GlobalizationMode.UseNls ? NlsNormalize(strInput, normalizationForm) : -// #if TARGET_MACCATALYST || TARGET_IOS || TARGET_TVOS -// GlobalizationMode.Hybrid ? -// NativeNormalize(strInput, normalizationForm) : -// IcuNormalize(strInput, normalizationForm); -// #else IcuNormalize(strInput, normalizationForm); -// #endif } } } From 544bea5c1389e8d91655d6262369b6b99c9201a3 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 16 Aug 2023 12:21:56 +0200 Subject: [PATCH 3/4] Changes requested by review --- .../System.Globalization.Native/pal_casing.m | 31 -------- .../pal_icushim_internal.h | 32 ++++++++ .../pal_normalization.m | 78 +++++++------------ 3 files changed, 61 insertions(+), 80 deletions(-) diff --git a/src/native/libs/System.Globalization.Native/pal_casing.m b/src/native/libs/System.Globalization.Native/pal_casing.m index 16467e6b9cb816..31fd647347daf1 100644 --- a/src/native/libs/System.Globalization.Native/pal_casing.m +++ b/src/native/libs/System.Globalization.Native/pal_casing.m @@ -55,37 +55,6 @@ } \ } -/** - * Append a code point to a string, overwriting 1 or 2 code units. - * The offset points to the current end of the string contents - * and is advanced (post-increment). - * "Safe" macro, checks for a valid code point. - * Converts code points outside of Basic Multilingual Plane into - * corresponding surrogate pairs if sufficient space in the string. - * High surrogate range: 0xD800 - 0xDBFF - * Low surrogate range: 0xDC00 - 0xDFFF - * If the code point is not valid or a trail surrogate does not fit, - * then isError is set to true. - * - * @param buffer const uint16_t * string buffer - * @param offset string offset, must be offset= (capacity)) /* insufficiently sized destination buffer */ { \ - (isError) = InsufficientBuffer; \ - } else if ((uint32_t)(codePoint) > 0x10ffff) /* invalid code point */ { \ - (isError) = InvalidCodePoint; \ - } else if ((uint32_t)(codePoint) <= 0xffff) { \ - (buffer)[(offset)++] = (uint16_t)(codePoint); \ - } else { \ - (buffer)[(offset)++] = (uint16_t)(((codePoint) >> 10) + 0xd7c0); \ - (buffer)[(offset)++] = (uint16_t)(((codePoint)&0x3ff) | 0xdc00); \ - } \ -} - /* Function: ChangeCaseNative diff --git a/src/native/libs/System.Globalization.Native/pal_icushim_internal.h b/src/native/libs/System.Globalization.Native/pal_icushim_internal.h index 9b5fd1a6c0be93..bc04acaf55b1e4 100644 --- a/src/native/libs/System.Globalization.Native/pal_icushim_internal.h +++ b/src/native/libs/System.Globalization.Native/pal_icushim_internal.h @@ -346,3 +346,35 @@ const char* GlobalizationNative_GetICUDataPathFallback(void); #endif #endif // !defined(STATIC_ICU) +#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) +/** + * Append a code point to a string, overwriting 1 or 2 code units. + * The offset points to the current end of the string contents + * and is advanced (post-increment). + * "Safe" macro, checks for a valid code point. + * Converts code points outside of Basic Multilingual Plane into + * corresponding surrogate pairs if sufficient space in the string. + * High surrogate range: 0xD800 - 0xDBFF + * Low surrogate range: 0xDC00 - 0xDFFF + * If the code point is not valid or a trail surrogate does not fit, + * then isError is set to true. + * + * @param buffer const uint16_t * string buffer + * @param offset string offset, must be offset= (capacity)) /* insufficiently sized destination buffer */ { \ + (isError) = InsufficientBuffer; \ + } else if ((uint32_t)(codePoint) > 0x10ffff) /* invalid code point */ { \ + (isError) = InvalidCodePoint; \ + } else if ((uint32_t)(codePoint) <= 0xffff) { \ + (buffer)[(offset)++] = (uint16_t)(codePoint); \ + } else { \ + (buffer)[(offset)++] = (uint16_t)(((codePoint) >> 10) + 0xd7c0); \ + (buffer)[(offset)++] = (uint16_t)(((codePoint)&0x3ff) | 0xdc00); \ + } \ +} +#endif diff --git a/src/native/libs/System.Globalization.Native/pal_normalization.m b/src/native/libs/System.Globalization.Native/pal_normalization.m index b3073747c65e1f..06360be8852563 100644 --- a/src/native/libs/System.Globalization.Native/pal_normalization.m +++ b/src/native/libs/System.Globalization.Native/pal_normalization.m @@ -7,6 +7,7 @@ #include "pal_normalization.h" #import +#if defined(TARGET_MACCATALYST) || defined(TARGET_IOS) || defined(TARGET_TVOS) static NSString* GetNormalizedStringForForm(NormalizationForm normalizationForm, NSString* sourceString) { switch (normalizationForm) @@ -29,8 +30,7 @@ IsNormalized Used by System.StringNormalizationExtensions.IsNormalized to detect if a string -is in a certain -Unicode Normalization Form. +is in a certain Unicode Normalization Form. Return values: 0: lpStr is not normalized. @@ -39,41 +39,13 @@ */ int32_t GlobalizationNative_IsNormalizedNative(NormalizationForm normalizationForm, const uint16_t* lpStr, int32_t cwStrLength) { - NSString *sourceString = [NSString stringWithCharacters: lpStr length: cwStrLength]; - NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); - - return normalizedString == NULL ? -1 : [sourceString isEqualToString: normalizedString]; -} + @autoreleasepool + { + NSString *sourceString = [NSString stringWithCharacters: lpStr length: cwStrLength]; + NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); -/** - * Append a code point to a string, overwriting 1 or 2 code units. - * The offset points to the current end of the string contents - * and is advanced (post-increment). - * "Safe" macro, checks for a valid code point. - * Converts code points outside of Basic Multilingual Plane into - * corresponding surrogate pairs if sufficient space in the string. - * High surrogate range: 0xD800 - 0xDBFF - * Low surrogate range: 0xDC00 - 0xDFFF - * If the code point is not valid or a trail surrogate does not fit, - * then isError is set to true. - * - * @param buffer const uint16_t * string buffer - * @param offset string offset, must be offset= (capacity)) /* insufficiently sized destination buffer */ { \ - (isError) = InsufficientBuffer; \ - } else if ((uint32_t)(codePoint) > 0x10ffff) /* invalid code point */ { \ - (isError) = InvalidCodePoint; \ - } else if ((uint32_t)(codePoint) <= 0xffff) { \ - (buffer)[(offset)++] = (uint16_t)(codePoint); \ - } else { \ - (buffer)[(offset)++] = (uint16_t)(((codePoint) >> 10) + 0xd7c0); \ - (buffer)[(offset)++] = (uint16_t)(((codePoint)&0x3ff) | 0xdc00); \ - } \ + return normalizedString == NULL ? -1 : [sourceString isEqualToString: normalizedString]; + } } /* @@ -81,8 +53,7 @@ int32_t GlobalizationNative_IsNormalizedNative(NormalizationForm normalizationFo NormalizeString Used by System.StringNormalizationExtensions.Normalize to normalize a string -into a certain -Unicode Normalization Form. +into a certain Unicode Normalization Form. Return values: 0: internal error during normalization. @@ -90,17 +61,26 @@ int32_t GlobalizationNative_IsNormalizedNative(NormalizationForm normalizationFo */ int32_t GlobalizationNative_NormalizeStringNative(NormalizationForm normalizationForm, const uint16_t* lpSource, int32_t cwSourceLength, uint16_t* lpDst, int32_t cwDstLength) { - NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; - NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); - int32_t index = 0; - int32_t dstIdx = 0, isError = 0; - uint16_t dstCodepoint; - while (index < normalizedString.length && dstIdx < cwDstLength) + @autoreleasepool { - dstCodepoint = [normalizedString characterAtIndex: index]; - Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError); - index++; - } + NSString *sourceString = [NSString stringWithCharacters: lpSource length: cwSourceLength]; + NSString *normalizedString = GetNormalizedStringForForm(normalizationForm, sourceString); + + if (normalizedString == NULL || normalizedString.length == 0) + { + return 0; + } - return isError || normalizedString == NULL ? 0 : [normalizedString length]; + int32_t index = 0, dstIdx = 0, isError = 0; + uint16_t dstCodepoint; + while (index < normalizedString.length) + { + dstCodepoint = [normalizedString characterAtIndex: index]; + Append(lpDst, dstIdx, cwDstLength, dstCodepoint, isError); + index++; + } + + return !isError ? [normalizedString length] : 0; + } } +#endif From c7d45f73f078c6aee0c387bc81784e0150a55870 Mon Sep 17 00:00:00 2001 From: Meri Khamoyan Date: Wed, 16 Aug 2023 12:22:12 +0200 Subject: [PATCH 4/4] Add new line --- src/native/libs/System.Globalization.Native/pal_normalization.m | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/libs/System.Globalization.Native/pal_normalization.m b/src/native/libs/System.Globalization.Native/pal_normalization.m index 06360be8852563..c31242ca36ef31 100644 --- a/src/native/libs/System.Globalization.Native/pal_normalization.m +++ b/src/native/libs/System.Globalization.Native/pal_normalization.m @@ -84,3 +84,4 @@ int32_t GlobalizationNative_NormalizeStringNative(NormalizationForm normalizatio } } #endif +