ICU-13851 case mapping data: when fetching delta make sure to read from start of exceptional values

X-SVN-Rev: 41550
This commit is contained in:
Markus Scherer 2018-06-24 21:12:22 +00:00
parent 4bc6ad328b
commit 99354ec034
4 changed files with 33 additions and 6 deletions

View File

@ -270,6 +270,7 @@ ucase_addCaseClosure(UChar32 c, const USetAdder *sa) {
}
}
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 @@ ucase_toFullLower(UChar32 c,
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 @@ toUpperOrTitle(UChar32 c,
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 @@ ucase_toFullFolding(UChar32 c,
}
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)) {

View File

@ -68,6 +68,7 @@ public:
void TestBug13127();
void TestInPlaceTitle();
void TestCaseMapEditsIteratorDocs();
void TestCaseMapGreekExtended();
private:
void assertGreekUpper(const char16_t *s, const char16_t *expected);
@ -113,6 +114,7 @@ StringCaseTest::runIndexedTest(int32_t index, UBool exec, const char *&name, cha
TESTCASE_AUTO(TestInPlaceTitle);
#endif
TESTCASE_AUTO(TestCaseMapEditsIteratorDocs);
TESTCASE_AUTO(TestCaseMapGreekExtended);
TESTCASE_AUTO_END;
}
@ -1685,4 +1687,17 @@ void StringCaseTest::TestCaseMapEditsIteratorDocs() {
}
}
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

View File

@ -318,6 +318,7 @@ public final class UCaseProps {
}
}
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 @@ public final class UCaseProps {
}
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 @@ public final class UCaseProps {
}
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 @@ public final class UCaseProps {
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)) {

View File

@ -1493,6 +1493,16 @@ public final class UCharacterCaseTest extends TestFmwk
}
}
@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");