ICU-13851 case mapping data: when fetching delta make sure to read from start of exceptional values
X-SVN-Rev: 41550
diff --git a/icu4c/source/common/ucase.cpp b/icu4c/source/common/ucase.cpp
index cbd5a6e..8414c52 100644
--- a/icu4c/source/common/ucase.cpp
+++ b/icu4c/source/common/ucase.cpp
@@ -270,6 +270,7 @@
}
}
if(HAS_SLOT(excWord, UCASE_EXC_DELTA)) {
+ pe=pe0;
int32_t delta;
GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
sa->add(sa->set, (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta);
@@ -1167,7 +1168,7 @@
if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_IS_UPPER_OR_TITLE(props)) {
int32_t delta;
- GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
+ GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta);
return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
}
if(HAS_SLOT(excWord, UCASE_EXC_LOWER)) {
@@ -1261,7 +1262,7 @@
if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_GET_TYPE(props)==UCASE_LOWER) {
int32_t delta;
- GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
+ GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta);
return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
}
if(!upperNotTitle && HAS_SLOT(excWord, UCASE_EXC_TITLE)) {
@@ -1469,7 +1470,7 @@
}
if(HAS_SLOT(excWord, UCASE_EXC_DELTA) && UCASE_IS_UPPER_OR_TITLE(props)) {
int32_t delta;
- GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe, delta);
+ GET_SLOT_VALUE(excWord, UCASE_EXC_DELTA, pe2, delta);
return (excWord&UCASE_EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
}
if(HAS_SLOT(excWord, UCASE_EXC_FOLD)) {
diff --git a/icu4c/source/test/intltest/strcase.cpp b/icu4c/source/test/intltest/strcase.cpp
index fe983da..3fb0584 100644
--- a/icu4c/source/test/intltest/strcase.cpp
+++ b/icu4c/source/test/intltest/strcase.cpp
@@ -68,6 +68,7 @@
void TestBug13127();
void TestInPlaceTitle();
void TestCaseMapEditsIteratorDocs();
+ void TestCaseMapGreekExtended();
private:
void assertGreekUpper(const char16_t *s, const char16_t *expected);
@@ -113,6 +114,7 @@
TESTCASE_AUTO(TestInPlaceTitle);
#endif
TESTCASE_AUTO(TestCaseMapEditsIteratorDocs);
+ TESTCASE_AUTO(TestCaseMapGreekExtended);
TESTCASE_AUTO_END;
}
@@ -1685,4 +1687,17 @@
}
}
+void StringCaseTest::TestCaseMapGreekExtended() {
+ // Ticket 13851
+ UnicodeString s(u"\u1F80\u1F88\u1FFC");
+ UnicodeString result(s);
+ result.toLower(Locale::getRoot());
+ assertEquals(u"lower", u"\u1F80\u1F80\u1FF3", result);
+#if !UCONFIG_NO_BREAK_ITERATION
+ result = s;
+ result.toTitle(nullptr, Locale::getRoot());
+ assertEquals(u"title", u"\u1F88\u1F80\u1FF3", result);
+#endif
+}
+
//#endif
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java
index ae267bb..a925507 100644
--- a/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java
+++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/UCaseProps.java
@@ -318,6 +318,7 @@
}
}
if(hasSlot(excWord, EXC_DELTA)) {
+ excOffset=excOffset0;
int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
set.add((excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta);
}
@@ -1131,7 +1132,7 @@
}
if(hasSlot(excWord, EXC_DELTA) && isUpperOrTitleFromProps(props)) {
- int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
+ int delta=getSlotValue(excWord, EXC_DELTA, excOffset2);
return (excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
}
if(hasSlot(excWord, EXC_LOWER)) {
@@ -1227,7 +1228,7 @@
}
if(hasSlot(excWord, EXC_DELTA) && getTypeFromProps(props)==LOWER) {
- int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
+ int delta=getSlotValue(excWord, EXC_DELTA, excOffset2);
return (excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
}
if(!upperNotTitle && hasSlot(excWord, EXC_TITLE)) {
@@ -1448,7 +1449,7 @@
return ~c;
}
if(hasSlot(excWord, EXC_DELTA) && isUpperOrTitleFromProps(props)) {
- int delta=getSlotValue(excWord, EXC_DELTA, excOffset);
+ int delta=getSlotValue(excWord, EXC_DELTA, excOffset2);
return (excWord&EXC_DELTA_IS_NEGATIVE)==0 ? c+delta : c-delta;
}
if(hasSlot(excWord, EXC_FOLD)) {
diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java
index 7ee1f55..1649a71 100644
--- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java
+++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/lang/UCharacterCaseTest.java
@@ -1493,6 +1493,16 @@
}
}
+ @Test
+ public void TestCaseMapGreekExtended() {
+ // Ticket 13851
+ String s = "\u1F80\u1F88\u1FFC";
+ String result = CaseMap.toLower().apply(Locale.ROOT, s);
+ assertEquals("lower", "\u1F80\u1F80\u1FF3", result);
+ result = CaseMap.toTitle().apply(Locale.ROOT, null, s);
+ assertEquals("title", "\u1F88\u1F80\u1FF3", result);
+ }
+
// private data members - test data --------------------------------------
private static final Locale TURKISH_LOCALE_ = new Locale("tr", "TR");