]> granicus.if.org Git - icu/commitdiff
ICU-20316 case mapping append unchanged text before calling low-level functions that...
authorMarkus Scherer <markus.icu@gmail.com>
Thu, 21 Feb 2019 04:17:48 +0000 (20:17 -0800)
committerMarkus Scherer <markus.icu@gmail.com>
Thu, 21 Feb 2019 18:01:16 +0000 (10:01 -0800)
icu4j/main/classes/core/src/com/ibm/icu/impl/CaseMapImpl.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java

index 2b30c02860101de2b8a7620f63afc408072e5473..bdd3073dd6ed2ce3ab8b39765e91283f83f16153 100644 (file)
@@ -486,6 +486,11 @@ public final class CaseMapImpl {
             } else {
                 c = lead;
             }
+            // We need to append unchanged text before calling the UCaseProps.toFullXyz() methods
+            // because they will sometimes append their mapping to dest,
+            // and that must be after copying the previous text.
+            appendUnchanged(src, prev, cpStart - prev, dest, options, edits);
+            prev = cpStart;
             if (caseLocale >= 0) {
                 if (iter == null) {
                     iter = new StringContextIterator(src, cpStart, srcIndex);
@@ -497,7 +502,6 @@ public final class CaseMapImpl {
                 c = UCaseProps.INSTANCE.toFullFolding(c, dest, options);
             }
             if (c >= 0) {
-                appendUnchanged(src, prev, cpStart - prev, dest, options, edits);
                 appendResult(c, dest, srcIndex - cpStart, options, edits);
                 prev = srcIndex;
             }
@@ -568,9 +572,13 @@ public final class CaseMapImpl {
             } else {
                 iter.setCPStartAndLimit(cpStart, srcIndex);
             }
+            // We need to append unchanged text before calling UCaseProps.toFullUpper()
+            // because it will sometimes append its mapping to dest,
+            // and that must be after copying the previous text.
+            appendUnchanged(src, prev, cpStart - prev, dest, options, edits);
+            prev = cpStart;
             c = UCaseProps.INSTANCE.toFullUpper(c, iter, dest, caseLocale);
             if (c >= 0) {
-                appendUnchanged(src, prev, cpStart - prev, dest, options, edits);
                 appendResult(c, dest, srcIndex - cpStart, options, edits);
                 prev = srcIndex;
             }
index 1649a718d708be75dd8c11d749446e27bbf60287..7d2948dfa0b45ae26e76f5d588662a1f743054b7 100644 (file)
@@ -960,8 +960,8 @@ public final class UCharacterCaseTest extends TestFmwk
         // Iterate once forward, once backward, to cover more runtime conditions.
         int srcLength = expSrcIndex;
         int destLength = expDestIndex;
-        List<Integer> srcIndexes = new ArrayList<Integer>();
-        List<Integer> destIndexes = new ArrayList<Integer>();
+        List<Integer> srcIndexes = new ArrayList<>();
+        List<Integer> destIndexes = new ArrayList<>();
         srcIndexes.add(-1);
         destIndexes.add(-1);
         int srcIndex = 0;
@@ -1503,6 +1503,18 @@ public final class UCharacterCaseTest extends TestFmwk
         assertEquals("title", "\u1F88\u1F80\u1FF3", result);
     }
 
+    @Test
+    public void TestFoldBug20316() {
+        String s = "廬ᾒ뻪ᣃइ垚Ⴡₓ렞체ꖲ갹ݖ䕷꾬쯎㊅ᦘᰄ㸜䡏遁럢豑黾奯㸀⊻줮끎蒹衤劔뽳趧熶撒쫃窩겨ཇ脌쵐嫑⟑겭㋋濜隣ᳰ봢ℼ櫩靛㉃炔鋳" +
+                "оे⳨ᦧྃ깢粣ᑤꇪ찃̹鵄ዤꛛᰙ⡝捣쯋톐蕩栭쥀뎊ᄯ৻恳〬昴껤룩列潱ᑮ煃鶖안꽊鹭宪帐❖ा쥈잔";
+        String result = CaseMap.fold().apply(s);
+        assertTrue("廬ᾒ...->廬ἢι...", result.startsWith("廬ἢι"));
+        s = "儊ẖ깸ᝓ恷ᇁ䜄쌼ꇸჃ䗑䘬䒥㈴槁蛚紆洔㖣믏亝醣黹Ά嶨䖕篕舀ꖧ₭ଯᒗ✧ԗ墖쁳㽎苊澎긁⾆⒞蠻왃囨ᡠ邏꾭⪐턣搤穳≠톲絋砖ሷ⠆" +
+                "瞏惢鵶剕듘ᅤ♟Ԡⴠ⊡鹔ጙ갑⣚堟ᣗ✸㕇絮䠎瘗⟡놥擢ꉭ佱ྪ飹痵⿑⨴츿璿僖㯷넴鋰膄釚겼ナ黪差";
+        result = CaseMap.fold().apply(s);
+        assertTrue("儊ẖ...->儊h\u0331...", result.startsWith("儊h\u0331"));
+    }
+
     // private data members - test data --------------------------------------
 
     private static final Locale TURKISH_LOCALE_ = new Locale("tr", "TR");
@@ -1747,7 +1759,7 @@ public final class UCharacterCaseTest extends TestFmwk
      */
     private String[] getUnicodeStrings(String str)
     {
-        List<String> v = new ArrayList<String>(10);
+        List<String> v = new ArrayList<>(10);
         int start = 0;
         for (int casecount = 4; casecount > 0; casecount --) {
             int end = str.indexOf("; ", start);