ICU-12085 manually integrate branch > trunk (had network problems committing updated branch)

X-SVN-Rev: 38311
This commit is contained in:
Peter Edberg 2016-02-15 17:58:23 +00:00
parent f74ad54c81
commit 086ee675a8
10 changed files with 214 additions and 48 deletions

View file

@ -26,6 +26,7 @@
#include "uresimp.h"
#include "ulist.h"
#include "ureslocs.h"
#include "ulocimp.h"
//#define UCURR_DEBUG_EQUIV 1
#ifdef UCURR_DEBUG_EQUIV
@ -367,7 +368,7 @@ idForLocale(const char* locale, char* countryAndVariant, int capacity, UErrorCod
// Extract the country name and variant name. We only
// recognize two variant names, EURO and PREEURO.
char variant[ULOC_FULLNAME_CAPACITY];
uloc_getCountry(locale, countryAndVariant, capacity, ec);
ulocimp_getRegionForSupplementalData(locale, FALSE, countryAndVariant, capacity, ec);
uloc_getVariant(locale, variant, sizeof(variant), ec);
if (variant[0] != 0) {
variantType = (uint32_t)(0 == uprv_strcmp(variant, VAR_EURO))
@ -2472,15 +2473,8 @@ static const UEnumeration defaultKeywordValues = {
U_CAPI UEnumeration *U_EXPORT2 ucurr_getKeywordValuesForLocale(const char *key, const char *locale, UBool commonlyUsed, UErrorCode* status) {
// Resolve region
char prefRegion[ULOC_FULLNAME_CAPACITY] = "";
int32_t prefRegionLength = 0;
prefRegionLength = uloc_getCountry(locale, prefRegion, sizeof(prefRegion), status);
if (prefRegionLength == 0) {
char loc[ULOC_FULLNAME_CAPACITY] = "";
uloc_addLikelySubtags(locale, loc, sizeof(loc), status);
/*prefRegionLength = */ uloc_getCountry(loc, prefRegion, sizeof(prefRegion), status);
}
char prefRegion[ULOC_COUNTRY_CAPACITY];
ulocimp_getRegionForSupplementalData(locale, TRUE, prefRegion, sizeof(prefRegion), status);
// Read value from supplementalData
UList *values = ulist_createEmptyList(status);

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 1997-2015, International Business Machines
* Copyright (C) 1997-2016, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*
@ -1348,6 +1348,56 @@ ulocimp_getCountry(const char *localeID,
return idLen;
}
// the following must at least allow for rg key value (6) plus terminator (1).
#define ULOC_RG_BUFLEN 8
U_CAPI int32_t U_EXPORT2
ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
char *region, int32_t regionCapacity, UErrorCode* status)
{
if (U_FAILURE(*status)) {
return 0;
}
char rgBuf[ULOC_RG_BUFLEN];
UErrorCode rgStatus = U_ZERO_ERROR;
// First check for rg keyword value
int32_t rgLen = uloc_getKeywordValue(localeID, "rg", rgBuf, ULOC_RG_BUFLEN, &rgStatus);
if (U_FAILURE(rgStatus) || rgLen != 6) {
rgLen = 0;
} else {
// rgBuf guaranteed to be zero terminated here, with text len 6
char *rgPtr = rgBuf;
for (; *rgPtr!= 0; rgPtr++) {
*rgPtr = uprv_toupper(*rgPtr);
}
rgLen = (uprv_strcmp(rgBuf+2, "ZZZZ") == 0)? 2: 0;
}
if (rgLen == 0) {
// No valid rg keyword value, try for unicode_region_subtag
rgLen = uloc_getCountry(localeID, rgBuf, ULOC_RG_BUFLEN, status);
if (U_FAILURE(*status)) {
rgLen = 0;
} else if (rgLen == 0 && inferRegion) {
// no unicode_region_subtag but inferRegion TRUE, try likely subtags
char locBuf[ULOC_FULLNAME_CAPACITY];
rgStatus = U_ZERO_ERROR;
(void)uloc_addLikelySubtags(localeID, locBuf, ULOC_FULLNAME_CAPACITY, &rgStatus);
if (U_SUCCESS(rgStatus)) {
rgLen = uloc_getCountry(locBuf, rgBuf, ULOC_RG_BUFLEN, status);
if (U_FAILURE(*status)) {
rgLen = 0;
}
}
}
}
rgBuf[rgLen] = 0;
uprv_strncpy(region, rgBuf, regionCapacity);
return u_terminateChars(region, regionCapacity, rgLen, status);
}
/**
* @param needSeparator if true, then add leading '_' if any variants
* are added to 'variant'

View file

@ -24,7 +24,8 @@ static icu::UVector* gLocExtTypeEntries = NULL;
typedef enum {
SPECIALTYPE_NONE = 0,
SPECIALTYPE_CODEPOINTS = 1,
SPECIALTYPE_REORDER_CODE = 2
SPECIALTYPE_REORDER_CODE = 2,
SPECIALTYPE_RG_KEY_VALUE = 4
} SpecialType;
typedef struct LocExtKeyData {
@ -215,6 +216,10 @@ initFromResourceBundle(UErrorCode& sts) {
specialTypes |= SPECIALTYPE_REORDER_CODE;
continue;
}
if (uprv_strcmp(legacyTypeId, "RG_KEY_VALUE") == 0) {
specialTypes |= SPECIALTYPE_RG_KEY_VALUE;
continue;
}
if (isTZ) {
// a timezone key uses a colon instead of a slash in the resource.
@ -450,6 +455,28 @@ isSpecialTypeReorderCode(const char* val) {
return (subtagLen >=3 && subtagLen <=8);
}
static UBool
isSpecialTypeRgKeyValue(const char* val) {
int32_t subtagLen = 0;
const char* p = val;
while (*p) {
if (*p == '-') {
if (subtagLen != 6) {
return FALSE;
}
subtagLen = 0;
} else if ( (subtagLen < 2 && uprv_isASCIILetter(*p)) ||
(subtagLen >= 2 && (*p == 'Z' || *p == 'z')) ) {
subtagLen++;
} else {
return FALSE;
}
p++;
}
return (subtagLen == 6);
return TRUE;
}
U_CFUNC const char*
ulocimp_toBcpKey(const char* key) {
if (!init()) {
@ -506,6 +533,9 @@ ulocimp_toBcpType(const char* key, const char* type, UBool* isKnownKey, UBool* i
if (!matched && keyData->specialTypes & SPECIALTYPE_REORDER_CODE) {
matched = isSpecialTypeReorderCode(type);
}
if (!matched && keyData->specialTypes & SPECIALTYPE_RG_KEY_VALUE) {
matched = isSpecialTypeRgKeyValue(type);
}
if (matched) {
if (isSpecialType != NULL) {
*isSpecialType = TRUE;
@ -548,6 +578,9 @@ ulocimp_toLegacyType(const char* key, const char* type, UBool* isKnownKey, UBool
if (!matched && keyData->specialTypes & SPECIALTYPE_REORDER_CODE) {
matched = isSpecialTypeReorderCode(type);
}
if (!matched && keyData->specialTypes & SPECIALTYPE_RG_KEY_VALUE) {
matched = isSpecialTypeRgKeyValue(type);
}
if (matched) {
if (isSpecialType != NULL) {
*isSpecialType = TRUE;

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2004-2014, International Business Machines
* Copyright (C) 2004-2016, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
@ -59,6 +59,35 @@ ulocimp_getCountry(const char *localeID,
char *country, int32_t countryCapacity,
const char **pEnd);
/**
* Get the region to use for supplemental data lookup. Uses
* (1) any region specified by locale tag "rg"; if none then
* (2) any unicode_region_tag in the locale ID; if none then
* (3) if inferRegion is TRUE, the region suggested by
* getLikelySubtags on the localeID.
* If no region is found, returns length 0.
*
* @param localeID
* The complete locale ID (with keywords) from which
* to get the region to use for supplemental data.
* @param inferRegion
* If TRUE, will try to infer region from localeID if
* no other region is found.
* @param region
* Buffer in which to put the region ID found; should
* have a capacity at least ULOC_COUNTRY_CAPACITY.
* @param regionCapacity
* The actual capacity of the region buffer.
* @param status
* Pointer to in/out UErrorCode value for latest status.
* @return
* The length of any region code found, or 0 if none.
* @internal ICU 57
*/
U_CAPI int32_t U_EXPORT2
ulocimp_getRegionForSupplementalData(const char *localeID, UBool inferRegion,
char *region, int32_t regionCapacity, UErrorCode* status);
U_CAPI const char * U_EXPORT2
locale_getKeywordsStart(const char *localeID);

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1997-2015, International Business Machines Corporation and *
* Copyright (C) 1997-2016, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -59,6 +59,7 @@
#include "olsontz.h"
#include "sharedcalendar.h"
#include "unifiedcache.h"
#include "ulocimp.h"
#if !UCONFIG_NO_SERVICE
static icu::ICULocaleService* gService = NULL;
@ -284,17 +285,10 @@ static ECalType getCalendarTypeForLocale(const char *locid) {
// when calendar keyword is not available or not supported, read supplementalData
// to get the default calendar type for the locale's region
char region[ULOC_COUNTRY_CAPACITY];
int32_t regionLen = 0;
regionLen = uloc_getCountry(canonicalName, region, sizeof(region) - 1, &status);
if (regionLen == 0) {
char fullLoc[256];
uloc_addLikelySubtags(locid, fullLoc, sizeof(fullLoc) - 1, &status);
regionLen = uloc_getCountry(fullLoc, region, sizeof(region) - 1, &status);
}
(void)ulocimp_getRegionForSupplementalData(canonicalName, TRUE, region, sizeof(region), &status);
if (U_FAILURE(status)) {
return CALTYPE_GREGORIAN;
}
region[regionLen] = 0;
// Read preferred calendar values from supplementalData calendarPreference
UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", &status);
@ -3806,11 +3800,13 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode&
return;
}
char region[ULOC_COUNTRY_CAPACITY];
(void)ulocimp_getRegionForSupplementalData(desiredLocale.getName(), TRUE, region, sizeof(region), &status);
// Read week data values from supplementalData week data
UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", &status);
ures_getByKey(rb, "weekData", rb, &status);
UResourceBundle *weekData = ures_getByKey(rb, useLocale.getCountry(), NULL, &status);
UResourceBundle *weekData = ures_getByKey(rb, region, NULL, &status);
if (status == U_MISSING_RESOURCE_ERROR && rb != NULL) {
status = U_ZERO_ERROR;
weekData = ures_getByKey(rb, "001", NULL, &status);

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1996-2015, International Business Machines
* Copyright (C) 1996-2016, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
@ -25,6 +25,7 @@
#include "ustrenum.h"
#include "uenumimp.h"
#include "ulist.h"
#include "ulocimp.h"
U_NAMESPACE_USE
@ -669,15 +670,8 @@ static const char * const CAL_TYPES[] = {
U_CAPI UEnumeration* U_EXPORT2
ucal_getKeywordValuesForLocale(const char * /* key */, const char* locale, UBool commonlyUsed, UErrorCode *status) {
// Resolve region
char prefRegion[ULOC_FULLNAME_CAPACITY] = "";
int32_t prefRegionLength = 0;
prefRegionLength = uloc_getCountry(locale, prefRegion, sizeof(prefRegion), status);
if (prefRegionLength == 0) {
char loc[ULOC_FULLNAME_CAPACITY] = "";
uloc_addLikelySubtags(locale, loc, sizeof(loc), status);
prefRegionLength = uloc_getCountry(loc, prefRegion, sizeof(prefRegion), status);
}
char prefRegion[ULOC_COUNTRY_CAPACITY];
(void)ulocimp_getRegionForSupplementalData(locale, TRUE, prefRegion, sizeof(prefRegion), status);
// Read preferred calendar values from supplementalData calendarPreference
UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", status);

View file

@ -1,7 +1,7 @@
/*
******************************************************************************
* *
* Copyright (C) 2003-2013, International Business Machines *
* Copyright (C) 2003-2016, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
@ -21,6 +21,7 @@
#include "unicode/ulocdata.h"
#include "uresimp.h"
#include "ureslocs.h"
#include "ulocimp.h"
#define MEASUREMENT_SYSTEM "MeasurementSystem"
#define PAPER_SIZE "PaperSize"
@ -189,16 +190,11 @@ ulocdata_getDelimiter(ULocaleData *uld, ULocaleDataDelimiterType type,
}
static UResourceBundle * measurementTypeBundleForLocale(const char *localeID, const char *measurementType, UErrorCode *status){
char fullLoc[ULOC_FULLNAME_CAPACITY];
char region[ULOC_COUNTRY_CAPACITY];
UResourceBundle *rb;
UResourceBundle *measTypeBundle = NULL;
/* The following code is basically copied from Calendar::setWeekData and
* Calendar::getCalendarTypeForLocale with adjustments for resource name
*/
uloc_addLikelySubtags(localeID, fullLoc, ULOC_FULLNAME_CAPACITY, status);
uloc_getCountry(fullLoc, region, ULOC_COUNTRY_CAPACITY, status);
ulocimp_getRegionForSupplementalData(localeID, TRUE, region, ULOC_COUNTRY_CAPACITY, status);
rb = ures_openDirect(NULL, "supplementalData", status);
ures_getByKey(rb, "measurementData", rb, status);

View file

@ -1,5 +1,5 @@
/********************************************************************
* Copyright (c) 1997-2014, International Business Machines
* Copyright (c) 1997-2016, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************
*
@ -85,6 +85,12 @@ static const UCalGetTypeTest ucalGetTypeTests[] = {
{ "th_TH", UCAL_DEFAULT, "buddhist" },
{ "th-TH-u-ca-gregory", UCAL_DEFAULT, "gregorian" },
{ "ja_JP@calendar=japanese", UCAL_GREGORIAN, "gregorian" },
{ "fr_CH", UCAL_DEFAULT, "gregorian" },
{ "fr_SA", UCAL_DEFAULT, "islamic-umalqura" },
{ "fr_CH@rg=sazzzz", UCAL_DEFAULT, "islamic-umalqura" },
{ "fr_CH@calendar=japanese;rg=sazzzz", UCAL_DEFAULT, "japanese" },
{ "fr_TH@rg=SA", UCAL_DEFAULT, "buddhist" }, /* ignore malformed rg tag */
{ "th@rg=SA", UCAL_DEFAULT, "buddhist" }, /* ignore malformed rg tag */
{ "", UCAL_GREGORIAN, "gregorian" },
{ NULL, UCAL_GREGORIAN, "gregorian" },
{ NULL, 0, NULL } /* terminator */
@ -1546,7 +1552,7 @@ void TestGregorianChange() {
}
static void TestGetKeywordValuesForLocale() {
#define PREFERRED_SIZE 15
#define PREFERRED_SIZE 16
#define MAX_NUMBER_OF_KEYWORDS 5
const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS+1] = {
{ "root", "gregorian", NULL, NULL, NULL, NULL },
@ -1564,8 +1570,9 @@ static void TestGetKeywordValuesForLocale() {
{ "en@calendar=islamic", "gregorian", NULL, NULL, NULL, NULL },
{ "zh_TW", "gregorian", "roc", "chinese", NULL, NULL },
{ "ar_IR", "persian", "gregorian", "islamic", "islamic-civil", "islamic-tbla" },
{ "th@rg=SAZZZZ", "islamic-umalqura", "gregorian", "islamic", "islamic-rgsa", NULL },
};
const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = { 1, 1, 1, 1, 2, 2, 2, 5, 5, 2, 2, 2, 1, 3, 5 };
const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = { 1, 1, 1, 1, 2, 2, 2, 5, 5, 2, 2, 2, 1, 3, 5, 4 };
UErrorCode status = U_ZERO_ERROR;
int32_t i, size, j;
UEnumeration *all, *pref;
@ -1724,6 +1731,8 @@ static const TestDaysOfWeekList testDays[] = {
{ "en_US", daysOfWeek_en_US, sizeof(daysOfWeek_en_US)/sizeof(daysOfWeek_en_US[0]) },
{ "ar_OM", daysOfWeek_ar_OM, sizeof(daysOfWeek_ar_OM)/sizeof(daysOfWeek_ar_OM[0]) },
{ "hi_IN", daysOfWeek_hi_IN, sizeof(daysOfWeek_hi_IN)/sizeof(daysOfWeek_hi_IN[0]) },
{ "en_US@rg=OMZZZZ", daysOfWeek_ar_OM, sizeof(daysOfWeek_ar_OM)/sizeof(daysOfWeek_ar_OM[0]) },
{ "hi@rg=USZZZZ", daysOfWeek_en_US, sizeof(daysOfWeek_en_US)/sizeof(daysOfWeek_en_US[0]) },
};
static const UChar logDateFormat[] = { 0x0045,0x0045,0x0045,0x0020,0x004D,0x004D,0x004D,0x0020,0x0064,0x0064,0x0020,0x0079,

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2015, International Business Machines Corporation and
* Copyright (c) 1997-2016, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/*****************************************************************************
@ -40,6 +40,7 @@
static void TestNullDefault(void);
static void TestNonexistentLanguageExemplars(void);
static void TestLocDataErrorCodeChaining(void);
static void TestLocDataWithRgTag(void);
static void TestLanguageExemplarsFallbacks(void);
static void TestDisplayNameBrackets(void);
@ -232,6 +233,7 @@ void addLocaleTest(TestNode** root)
TESTCASE(TestDisplayNameWarning);
TESTCASE(TestNonexistentLanguageExemplars);
TESTCASE(TestLocDataErrorCodeChaining);
TESTCASE(TestLocDataWithRgTag);
TESTCASE(TestLanguageExemplarsFallbacks);
TESTCASE(TestCalendar);
TESTCASE(TestDateFormat);
@ -2705,6 +2707,36 @@ static void TestLocDataErrorCodeChaining(void) {
}
}
typedef struct {
const char* locale;
UMeasurementSystem measureSys;
} LocToMeasureSys;
static const LocToMeasureSys locToMeasures[] = {
{ "fr_FR", UMS_SI },
{ "en", UMS_US },
{ "en_GB", UMS_UK },
{ "fr_FR@rg=GBZZZZ", UMS_UK },
{ "en@rg=frzzzz", UMS_SI },
{ "en_GB@rg=USZZZZ", UMS_US },
{ NULL, (UMeasurementSystem)0 } /* terminator */
};
static void TestLocDataWithRgTag(void) {
const LocToMeasureSys* locToMeasurePtr = locToMeasures;
for (; locToMeasurePtr->locale != NULL; locToMeasurePtr++) {
UErrorCode status = U_ZERO_ERROR;
UMeasurementSystem measureSys = ulocdata_getMeasurementSystem(locToMeasurePtr->locale, &status);
if (U_FAILURE(status)) {
log_data_err("ulocdata_getMeasurementSystem(\"%s\", ...) failed: %s - Are you missing data?\n",
locToMeasurePtr->locale, u_errorName(status));
} else if (measureSys != locToMeasurePtr->measureSys) {
log_err("ulocdata_getMeasurementSystem(\"%s\", ...), expected %d, got %d\n",
locToMeasurePtr->locale, (int) locToMeasurePtr->measureSys, (int)measureSys);
}
}
}
static void TestLanguageExemplarsFallbacks(void) {
/* Test that en_US fallsback, but en doesn't fallback. */
UErrorCode ec = U_ZERO_ERROR;

View file

@ -1,6 +1,6 @@
/********************************************************************
* COPYRIGHT:
* Copyright (c) 1997-2014, International Business Machines Corporation
* Copyright (c) 1997-2016, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************/
/*******************************************************************************
@ -25,6 +25,7 @@
#include "unicode/uloc.h"
#include "unicode/unum.h"
#include "unicode/ustring.h"
#include "unicode/putil.h"
#include "cintltst.h"
#include "cnmdptst.h"
#include "cmemory.h"
@ -868,7 +869,7 @@ static void TestCurrencyKeywords(void)
}
static void TestGetKeywordValuesForLocale(void) {
#define PREFERRED_SIZE 12
#define PREFERRED_SIZE 15
#define MAX_NUMBER_OF_KEYWORDS 4
const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS] = {
{ "root", "USD", "USN", NULL },
@ -884,9 +885,19 @@ static void TestGetKeywordValuesForLocale(void) {
{ "en@currency=CAD", "USD", "USN", NULL },
{ "fr@currency=zzz", "EUR", NULL, NULL },
{ "de_DE@currency=DEM", "EUR", NULL, NULL },
{ "en_US@rg=THZZZZ", "THB", NULL, NULL },
{ "de@rg=USZZZZ", "USD", "USN", NULL },
{ "en_US@currency=CAD;rg=THZZZZ", "THB", NULL, NULL },
};
const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = {
2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1
2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1
};
/* ucurr_forLocale results for same locales; "" if no result expected */
const char *FORLOCALE[PREFERRED_SIZE] = {
"", "", "USD", "",
"THB", "", "EUR", "",
"ILS", "CAD", "ZZZ", "DEM",
"THB", "USD", "CAD"
};
UErrorCode status = U_ZERO_ERROR;
int32_t i, j, size;
@ -905,6 +916,10 @@ static void TestGetKeywordValuesForLocale(void) {
}
for (i = 0; i < PREFERRED_SIZE; i++) {
UChar getCurrU[4];
int32_t getCurrLen;
status = U_ZERO_ERROR;
pref = NULL;
all = NULL;
loc = PREFERRED[i][0];
@ -972,6 +987,24 @@ static void TestGetKeywordValuesForLocale(void) {
}
uenum_close(all);
status = U_ZERO_ERROR;
getCurrLen = ucurr_forLocale(loc, getCurrU, 4, &status);
if(U_FAILURE(status)) {
if (FORLOCALE[i][0] != 0) {
log_err("ERROR: ucurr_forLocale %s, status %s\n", loc, u_errorName(status));
}
} else if (getCurrLen != 3) {
if (FORLOCALE[i][0] != 0 || getCurrLen != -1) {
log_err("ERROR: ucurr_forLocale %s, returned len %d\n", loc, getCurrLen);
}
} else {
char getCurrB[4];
u_UCharsToChars(getCurrU, getCurrB, 4);
if ( uprv_strncmp(getCurrB, FORLOCALE[i], 4) != 0 ) {
log_err("ERROR: ucurr_forLocale %s, expected %s, got %s\n", loc, FORLOCALE[i], getCurrB);
}
}
}
uenum_close(ALL);