Skip to content

Commit

Permalink
[iOS][non-icu] HybridGlobalization support IgnoreKanaType (#96002)
Browse files Browse the repository at this point in the history
Implement IgnoreKanaType on hybrid mode
  • Loading branch information
mkhamoyan authored Dec 15, 2023
1 parent 99cfd79 commit 2987aba
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 153 deletions.
7 changes: 3 additions & 4 deletions docs/design/features/globalization-hybrid-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,8 @@ The number of `CompareOptions` and `NSStringCompareOptions` combinations are lim

- `IgnoreSymbols` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`.

- `IgnoreKanaType` is not supported because there is no equivalent in native api. Throws `PlatformNotSupportedException`.
- `IgnoreKanaType` is implemented using [`kCFStringTransformHiraganaKatakana`](https://developer.apple.com/documentation/corefoundation/kcfstringtransformhiraganakatakana?language=objc) then comparing strings.


- `None`:

Expand Down Expand Up @@ -419,9 +420,7 @@ The number of `CompareOptions` and `NSStringCompareOptions` combinations are lim

- All combinations that contain below `CompareOptions` always throw `PlatformNotSupportedException`:

`IgnoreSymbols`,

`IgnoreKanaType`,
`IgnoreSymbols`

## String starts with / ends with

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ private static void AssertComparisonSupported(CompareOptions options)
}

private const CompareOptions SupportedCompareOptions = CompareOptions.None | CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace |
CompareOptions.IgnoreWidth | CompareOptions.StringSort;
CompareOptions.IgnoreWidth | CompareOptions.StringSort | CompareOptions.IgnoreKanaType;

private static string GetPNSE(CompareOptions options) =>
SR.Format(SR.PlatformNotSupported_HybridGlobalizationWithCompareOptions, options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,24 @@ public static IEnumerable<object[]> Compare_TestData()
CompareOptions validIgnoreKanaTypeOption = PlatformDetection.IsHybridGlobalizationOnBrowser ?
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase :
CompareOptions.IgnoreKanaType;
// In HybridGlobalization, IgnoreKanaType is not supported on OSX
if (!PlatformDetection.IsHybridGlobalizationOnOSX)
yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u304D \u3083", "\u30AD\u3083", validIgnoreKanaTypeOption, -1 };
yield return new object[] { s_invariantCompare, "\u3044", "I", validIgnoreKanaTypeOption, 1 };
yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u3060", "\u305F", validIgnoreKanaTypeOption, 1 };
yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u68EE\u9D0E\u5916", "\u68EE\u9DD7\u5916", validIgnoreKanaTypeOption, -1 };
yield return new object[] { s_invariantCompare, "\u2019", "'", validIgnoreKanaTypeOption, 1 };
yield return new object[] { s_invariantCompare, "", "'", validIgnoreKanaTypeOption, -1 };
yield return new object[] { s_invariantCompare, "\u30FC", "\uFF70", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase, 0 };
// PlatformDetection.IsHybridGlobalizationOnBrowser does not support IgnoreWidth
if (!PlatformDetection.IsHybridGlobalizationOnBrowser)
{
yield return new object[] { s_invariantCompare, "\u3042", "\u30A2", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u30E3", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u304D\u3083", "\u30AD\u3083", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u304D \u3083", "\u30AD\u3083", validIgnoreKanaTypeOption, -1 };
yield return new object[] { s_invariantCompare, "\u3044", "I", validIgnoreKanaTypeOption, 1 };
yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u30D6\u30D9\u30DC", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u3070\u3073\u3076\u3079\u307C", "\u30D0\u30D3\u3076\u30D9\u30DC", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u3060", "\u305F", validIgnoreKanaTypeOption, 1 };
yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", validIgnoreKanaTypeOption, 0 };
yield return new object[] { s_invariantCompare, "\u68EE\u9D0E\u5916", "\u68EE\u9DD7\u5916", validIgnoreKanaTypeOption, -1 };
yield return new object[] { s_invariantCompare, "\u2019", "'", validIgnoreKanaTypeOption, 1 };
yield return new object[] { s_invariantCompare, "", "'", validIgnoreKanaTypeOption, -1 };
yield return new object[] { s_invariantCompare, "\u30FC", "\uFF70", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase, 0 };
// PlatformDetection.IsHybridGlobalizationOnBrowser does not support IgnoreWidth
if (!PlatformDetection.IsHybridGlobalizationOnBrowser)
{
yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, 0 };
yield return new object[] { s_invariantCompare, "'\u3000'", "' '", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, 0 };
}
yield return new object[] { s_invariantCompare, "\u3042", "\uFF71", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, 0 };
yield return new object[] { s_invariantCompare, "'\u3000'", "' '", CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : 0 };
}

yield return new object[] { s_invariantCompare, "\u6FA4", "\u6CA2", CompareOptions.None, 1 };
Expand Down Expand Up @@ -264,12 +260,8 @@ public static IEnumerable<object[]> Compare_TestData()
// in HybridGlobalization on Browser IgnoreKanaType is supported only for "ja"
var kanaComparison = PlatformDetection.IsHybridGlobalizationOnBrowser ? s_japaneseCompare : s_invariantCompare;

// In HybridGlobalization mode on OSX IgnoreKanaType is not supported
if (!PlatformDetection.IsHybridGlobalizationOnOSX)
{
yield return new object[] { kanaComparison, "\u3060", "\u30C0", CompareOptions.IgnoreKanaType, 0 };
yield return new object[] { kanaComparison, "c", "C", CompareOptions.IgnoreKanaType, -1 };
}
yield return new object[] { kanaComparison, "\u3060", "\u30C0", CompareOptions.IgnoreKanaType, 0 };
yield return new object[] { kanaComparison, "c", "C", CompareOptions.IgnoreKanaType, -1 };

yield return new object[] { s_invariantCompare, "\u3060", "\u30C0", CompareOptions.IgnoreCase, PlatformDetection.IsHybridGlobalizationOnOSX ? 1 : s_expectedHiraganaToKatakanaCompare };

Expand All @@ -293,15 +285,12 @@ public static IEnumerable<object[]> Compare_TestData()
// Misc differences between platforms
bool useNls = PlatformDetection.IsNlsGlobalization;

if (!PlatformDetection.IsHybridGlobalizationOnOSX)
{
var japaneseCmp = PlatformDetection.IsHybridGlobalizationOnBrowser ?
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase :
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase;
var japaneseCmp = PlatformDetection.IsHybridGlobalizationOnBrowser ?
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase :
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase;

yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", japaneseCmp, useNls ? 1: 0 };
yield return new object[] { s_invariantCompare, "'\u3000'", "''", japaneseCmp, useNls ? 1 : -1 };
}
yield return new object[] { s_invariantCompare, "\u3042", "\u30A1", japaneseCmp, useNls || PlatformDetection.IsHybridGlobalizationOnOSX ? 1: 0 };
yield return new object[] { s_invariantCompare, "'\u3000'", "''", japaneseCmp, useNls ? 1 : -1 };

yield return new object[] { s_invariantCompare, "\u30BF", "\uFF80", CompareOptions.None, useNls ? 1 : -1 };
yield return new object[] { s_invariantCompare, "'\u3000'", "''", CompareOptions.None, useNls ? 1 : -1 };
Expand Down Expand Up @@ -339,7 +328,6 @@ public void CompareWithUnassignedChars()
}

[ConditionalTheory(nameof(IsNotWindowsKanaRegressedVersion))]
[SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS | TestPlatforms.OSX, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
[MemberData(nameof(Compare_Kana_TestData))]
public void CompareWithKana(CompareInfo compareInfo, string string1, string string2, CompareOptions options, int expected)
{
Expand Down Expand Up @@ -525,7 +513,6 @@ public void Compare_Invalid()
}

[Fact]
[SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS | TestPlatforms.OSX, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
public void TestIgnoreKanaAndWidthCases()
{
for (char c = '\uFF41'; c <= '\uFF5A'; c++)
Expand All @@ -536,15 +523,16 @@ public void TestIgnoreKanaAndWidthCases()

// Edge case of the Ignore Width.
Assert.False(string.Compare("\u3162\u3163", "\uFFDB\uFFDC", CultureInfo.InvariantCulture, CompareOptions.None) == 0, $"Expect '0x3162 0x3163' != '0xFFDB 0xFFDC'");
if (!PlatformDetection.IsHybridGlobalizationOnBrowser)
if (!PlatformDetection.IsHybridGlobalization)
Assert.True(string.Compare("\u3162\u3163", "\uFFDB\uFFDC", CultureInfo.InvariantCulture, CompareOptions.IgnoreWidth) == 0, "Expect '0x3162 0x3163' == '0xFFDB 0xFFDC'");

const char hiraganaStart = '\u3041';
const char hiraganaEnd = '\u3096';
const int hiraganaToKatakanaOffset = 0x30a1 - 0x3041;

// in HybridGlobalization on Browser IgnoreKanaType is supported only for "ja-JP"
CultureInfo ignoreKanaTypeTestedCulture = PlatformDetection.IsHybridGlobalizationOnBrowser ? new CultureInfo("ja-JP") : CultureInfo.InvariantCulture;
// in HybridGlobalization on OSX behavior is different for CultureInfo.InvariantCulture
CultureInfo ignoreKanaTypeTestedCulture = PlatformDetection.IsHybridGlobalization ? new CultureInfo("ja-JP") : CultureInfo.InvariantCulture;

for (Char hiraganaChar = hiraganaStart; hiraganaChar <= hiraganaEnd; hiraganaChar++)
{
Expand Down Expand Up @@ -572,6 +560,24 @@ public static IEnumerable<object[]> Compare_HiraganaAndKatakana_TestData()
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase,
CompareOptions.Ordinal,
CompareOptions.OrdinalIgnoreCase,
} : PlatformDetection.IsHybridGlobalizationOnOSX ?
new[] {
CompareOptions.None,
CompareOptions.IgnoreCase,
CompareOptions.IgnoreNonSpace,
CompareOptions.IgnoreKanaType,
CompareOptions.IgnoreWidth,
CompareOptions.Ordinal,
CompareOptions.OrdinalIgnoreCase,
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase,
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreNonSpace,
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace,
CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase,
CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace,
CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace,
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase,
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreNonSpace,
CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace,
} :
new[] {
CompareOptions.None,
Expand Down Expand Up @@ -621,7 +627,6 @@ public static IEnumerable<object[]> Compare_HiraganaAndKatakana_TestData()
}

[Theory]
[SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.MacCatalyst | TestPlatforms.tvOS | TestPlatforms.OSX, "Not supported on Browser, iOS, MacCatalyst, or tvOS.")]
[MemberData(nameof(Compare_HiraganaAndKatakana_TestData))]
public void TestHiraganaAndKatakana(CompareOptions[] optionsPositive, CompareOptions[] optionsNegative)
{
Expand Down
Loading

0 comments on commit 2987aba

Please sign in to comment.