]> granicus.if.org Git - icu/commitdiff
ICU-12085 manually integrate branch > trunk (had network problems committing updated...
authorPeter Edberg <pedberg@unicode.org>
Mon, 15 Feb 2016 17:58:23 +0000 (17:58 +0000)
committerPeter Edberg <pedberg@unicode.org>
Mon, 15 Feb 2016 17:58:23 +0000 (17:58 +0000)
X-SVN-Rev: 38311

icu4c/source/common/ucurr.cpp
icu4c/source/common/uloc.cpp
icu4c/source/common/uloc_keytype.cpp
icu4c/source/common/ulocimp.h
icu4c/source/i18n/calendar.cpp
icu4c/source/i18n/ucal.cpp
icu4c/source/i18n/ulocdata.c
icu4c/source/test/cintltst/ccaltst.c
icu4c/source/test/cintltst/cloctst.c
icu4c/source/test/cintltst/cnmdptst.c

index fce330569adcebf4652fa0ddc6fa1855a569366b..40a5591c42922f7fb7896484d16e2c9e5d69c663 100644 (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);
index 32a06bf84fccd5dcf9a611a0d8fc562da7c5a962..8959d253863b2575ecfcc948ad9e19a3e670f6f3 100644 (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'
index adca57821deebac7cc00c212e3e24541f29d8e3e..811da505a3165e29c990aca9d57d18c46a70fc6d 100644 (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;
index 164a730c0057d9b0bbfbba53095768bb182ad63d..d06db3fb2ac5e0411ef1e72da15495134e56417e 100644 (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);
 
index d07269d75c8fb0f01939b29d986f5ffe22db2055..1cd18d3a4fa0cef6ef9ddf1e345fac779fba2e78 100644 (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);
index dbbd711a3e39252cb6d4b2010e76834e0525d7aa..754eef9a6a5b2e6a33087f28aa085672f1ccee45 100644 (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);
index 48902f8655cdb6dfe4d842d9312219032a9c5b45..1f602444bd0fc9192bb8bc0780d042e1bcea549d 100644 (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);
index 4571cda1b4287fdb6cf53e9e1d479b2221b72233..909815eb3ac29071d0acc9fc3934fdb65b5235b7 100644 (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,
index 7531ffe46e7bfc10c9cce52059818552cecafd8a..bb61ed6bb6594c9edba0cd9d53c0b6b925b3e7f3 100644 (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;
index 8b3cbd61d245c5f14d2662cd81df209a1f0c95b9..b096b7732be5e36366e783c13ef733a1193f3ec8 100644 (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);