#include "uresimp.h"
#include "ulist.h"
#include "ureslocs.h"
+#include "ulocimp.h"
//#define UCURR_DEBUG_EQUIV 1
#ifdef UCURR_DEBUG_EQUIV
// 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))
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);
/*
**********************************************************************
-* Copyright (C) 1997-2015, International Business Machines
+* Copyright (C) 1997-2016, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*
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'
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 {
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.
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()) {
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;
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;
/*
**********************************************************************
-* Copyright (C) 2004-2014, International Business Machines
+* Copyright (C) 2004-2016, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
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);
/*
*******************************************************************************
-* Copyright (C) 1997-2015, International Business Machines Corporation and *
+* Copyright (C) 1997-2016, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
#include "olsontz.h"
#include "sharedcalendar.h"
#include "unifiedcache.h"
+#include "ulocimp.h"
#if !UCONFIG_NO_SERVICE
static icu::ICULocaleService* gService = NULL;
// 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);
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);
/*
*******************************************************************************
-* Copyright (C) 1996-2015, International Business Machines
+* Copyright (C) 1996-2016, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
*/
#include "ustrenum.h"
#include "uenumimp.h"
#include "ulist.h"
+#include "ulocimp.h"
U_NAMESPACE_USE
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);
/*
******************************************************************************
* *
-* Copyright (C) 2003-2013, International Business Machines *
+* Copyright (C) 2003-2016, International Business Machines *
* Corporation and others. All Rights Reserved. *
* *
******************************************************************************
#include "unicode/ulocdata.h"
#include "uresimp.h"
#include "ureslocs.h"
+#include "ulocimp.h"
#define MEASUREMENT_SYSTEM "MeasurementSystem"
#define PAPER_SIZE "PaperSize"
}
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);
/********************************************************************
- * Copyright (c) 1997-2014, International Business Machines
+ * Copyright (c) 1997-2016, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************
*
{ "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 */
}
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 },
{ "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;
{ "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,
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2015, International Business Machines Corporation and
+ * Copyright (c) 1997-2016, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************/
/*****************************************************************************
static void TestNullDefault(void);
static void TestNonexistentLanguageExemplars(void);
static void TestLocDataErrorCodeChaining(void);
+static void TestLocDataWithRgTag(void);
static void TestLanguageExemplarsFallbacks(void);
static void TestDisplayNameBrackets(void);
TESTCASE(TestDisplayNameWarning);
TESTCASE(TestNonexistentLanguageExemplars);
TESTCASE(TestLocDataErrorCodeChaining);
+ TESTCASE(TestLocDataWithRgTag);
TESTCASE(TestLanguageExemplarsFallbacks);
TESTCASE(TestCalendar);
TESTCASE(TestDateFormat);
}
}
+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;
/********************************************************************
* COPYRIGHT:
- * Copyright (c) 1997-2014, International Business Machines Corporation
+ * Copyright (c) 1997-2016, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************/
/*******************************************************************************
#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"
}
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 },
{ "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;
}
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];
}
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);