ICU-20321 Fix ultag_isUnicodeLocaleKey
Returns false when passingin alphanum digit. Sync with UTS35 https://www.unicode.org/reports/tr35/#Unicode_locale_identifier address review feedback add unit tests. Fix Java too add test cases to c++ Fix format change test case
This commit is contained in:
parent
a184153a2c
commit
9453dcfc19
@ -608,7 +608,7 @@ ultag_isUnicodeLocaleKey(const char* s, int32_t len) {
|
|||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
len = (int32_t)uprv_strlen(s);
|
len = (int32_t)uprv_strlen(s);
|
||||||
}
|
}
|
||||||
if (len == 2 && _isAlphaNumericString(s, len)) {
|
if (len == 2 && (ISALPHA(*s) || ISNUMERIC(*s)) && ISALPHA(s[1])) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -53,6 +53,7 @@ static void TestUnicodeDefines(void);
|
|||||||
static void TestIsRightToLeft(void);
|
static void TestIsRightToLeft(void);
|
||||||
static void TestBadLocaleIDs(void);
|
static void TestBadLocaleIDs(void);
|
||||||
static void TestBug20370(void);
|
static void TestBug20370(void);
|
||||||
|
static void TestBug20321UnicodeLocaleKey(void);
|
||||||
|
|
||||||
void PrintDataTable();
|
void PrintDataTable();
|
||||||
|
|
||||||
@ -268,6 +269,7 @@ void addLocaleTest(TestNode** root)
|
|||||||
TESTCASE(TestToLegacyType);
|
TESTCASE(TestToLegacyType);
|
||||||
TESTCASE(TestBadLocaleIDs);
|
TESTCASE(TestBadLocaleIDs);
|
||||||
TESTCASE(TestBug20370);
|
TESTCASE(TestBug20370);
|
||||||
|
TESTCASE(TestBug20321UnicodeLocaleKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6287,6 +6289,39 @@ static void TestToUnicodeLocaleKey(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void TestBug20321UnicodeLocaleKey(void)
|
||||||
|
{
|
||||||
|
// key = alphanum alpha ;
|
||||||
|
static const char* invalid[] = {
|
||||||
|
"a0",
|
||||||
|
"00",
|
||||||
|
"a@",
|
||||||
|
"0@",
|
||||||
|
"@a",
|
||||||
|
"@a",
|
||||||
|
"abc",
|
||||||
|
"0bc",
|
||||||
|
};
|
||||||
|
for (int i = 0; i < UPRV_LENGTHOF(invalid); i++) {
|
||||||
|
const char* bcpKey = NULL;
|
||||||
|
bcpKey = uloc_toUnicodeLocaleKey(invalid[i]);
|
||||||
|
if (bcpKey != NULL) {
|
||||||
|
log_err("toUnicodeLocaleKey: keyword=%s => %s, expected=NULL\n", invalid[i], bcpKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static const char* valid[] = {
|
||||||
|
"aa",
|
||||||
|
"0a",
|
||||||
|
};
|
||||||
|
for (int i = 0; i < UPRV_LENGTHOF(valid); i++) {
|
||||||
|
const char* bcpKey = NULL;
|
||||||
|
bcpKey = uloc_toUnicodeLocaleKey(valid[i]);
|
||||||
|
if (bcpKey == NULL) {
|
||||||
|
log_err("toUnicodeLocaleKey: keyword=%s => NULL, expected!=NULL\n", valid[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void TestToLegacyKey(void)
|
static void TestToLegacyKey(void)
|
||||||
{
|
{
|
||||||
/* $IN specifies the result should be the input pointer itself */
|
/* $IN specifies the result should be the input pointer itself */
|
||||||
|
@ -93,8 +93,9 @@ public class UnicodeLocaleExtension extends Extension {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isKey(String s) {
|
public static boolean isKey(String s) {
|
||||||
// 2alphanum
|
// key = alphanum alpha ;
|
||||||
return (s.length() == 2) && AsciiUtil.isAlphaNumericString(s);
|
return (s.length() == 2) && AsciiUtil.isAlphaNumeric(s.charAt(0)) &&
|
||||||
|
AsciiUtil.isAlpha(s.charAt(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isTypeSubtag(String s) {
|
public static boolean isTypeSubtag(String s) {
|
||||||
|
@ -82,12 +82,12 @@ public class LocaleBuilderTest extends TestFmwk {
|
|||||||
{"E", "z", "ExtZ", "L", "en", "E", "z", null, "T", "en", "en"},
|
{"E", "z", "ExtZ", "L", "en", "E", "z", null, "T", "en", "en"},
|
||||||
{"E", "a", "x", "X"},
|
{"E", "a", "x", "X"},
|
||||||
{"E", "a", "abc_def", "T", "und-a-abc-def", "@a=abc-def"},
|
{"E", "a", "abc_def", "T", "und-a-abc-def", "@a=abc-def"},
|
||||||
// Design limitation - typeless u extension keyword 00 below is interpreted as a boolean value true/yes.
|
// Design limitation - typeless u extension keyword 0a below is interpreted as a boolean value true/yes.
|
||||||
// With the legacy keyword syntax, "yes" is used for such boolean value instead of "true".
|
// With the legacy keyword syntax, "yes" is used for such boolean value instead of "true".
|
||||||
// However, once the legacy keyword is translated back to BCP 47 u extension, key "00" is unknown,
|
// However, once the legacy keyword is translated back to BCP 47 u extension, key "0a" is unknown,
|
||||||
// so "yes" is preserved - not mapped to "true". We could change the code to automatically transform
|
// so "yes" is preserved - not mapped to "true". We could change the code to automatically transform
|
||||||
// "yes" to "true", but it will break roundtrip conversion if BCP 47 u extension has "00-yes".
|
// "yes" to "true", but it will break roundtrip conversion if BCP 47 u extension has "0a-yes".
|
||||||
{"L", "en", "E", "u", "bbb-aaa-00", "T", "en-u-aaa-bbb-00-yes", "en@00=yes;attribute=aaa-bbb"},
|
{"L", "en", "E", "u", "bbb-aaa-0a", "T", "en-u-aaa-bbb-0a-yes", "en@0a=yes;attribute=aaa-bbb"},
|
||||||
{"L", "fr", "R", "FR", "P", "Yoshito-ICU", "T", "fr-FR-x-yoshito-icu", "fr_FR@x=yoshito-icu"},
|
{"L", "fr", "R", "FR", "P", "Yoshito-ICU", "T", "fr-FR-x-yoshito-icu", "fr_FR@x=yoshito-icu"},
|
||||||
{"L", "ja", "R", "jp", "K", "ca", "japanese", "T", "ja-JP-u-ca-japanese", "ja_JP@calendar=japanese"},
|
{"L", "ja", "R", "jp", "K", "ca", "japanese", "T", "ja-JP-u-ca-japanese", "ja_JP@calendar=japanese"},
|
||||||
{"K", "co", "PHONEBK", "K", "ca", "gregory", "L", "De", "T", "de-u-ca-gregory-co-phonebk", "de@calendar=gregorian;collation=phonebook"},
|
{"K", "co", "PHONEBK", "K", "ca", "gregory", "L", "De", "T", "de-u-ca-gregory-co-phonebk", "de@calendar=gregorian;collation=phonebook"},
|
||||||
|
@ -4696,6 +4696,36 @@ public class ULocaleTest extends TestFmwk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void TestBug20321UnicodeLocaleKey() {
|
||||||
|
// key = alphanum alpha ;
|
||||||
|
String[] INVALID = {
|
||||||
|
"a0",
|
||||||
|
"00",
|
||||||
|
"a@",
|
||||||
|
"0@",
|
||||||
|
"@a",
|
||||||
|
"@a",
|
||||||
|
"abc",
|
||||||
|
"0bc",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String invalid : INVALID) {
|
||||||
|
String bcpKey = ULocale.toUnicodeLocaleKey(invalid);
|
||||||
|
assertNull("keyword=" + invalid, bcpKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] VALID = {
|
||||||
|
"aa",
|
||||||
|
"0a",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String valid : VALID) {
|
||||||
|
String bcpKey = ULocale.toUnicodeLocaleKey(valid);
|
||||||
|
assertEquals("keyword=" + valid, valid, bcpKey);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void TestToLegacyKey() {
|
public void TestToLegacyKey() {
|
||||||
String[][] DATA = {
|
String[][] DATA = {
|
||||||
|
Loading…
Reference in New Issue
Block a user