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); rb = ures_openDirect(NULL, "supplementalData", status); ures_getByKey(rb, "measurementData", rb, status); if (rb != NULL) { UResourceBundle *measDataBundle = ures_getByKey(rb, region, NULL, status); if (U_SUCCESS(*status)) { measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status); } if (*status == U_MISSING_RESOURCE_ERROR) { *status = U_ZERO_ERROR; if (measDataBundle != NULL) { ures_close(measDataBundle); } measDataBundle = ures_getByKey(rb, "001", NULL, status); measTypeBundle = ures_getByKey(measDataBundle, measurementType, NULL, status); } ures_close(measDataBundle); } ures_close(rb); return measTypeBundle; }
static jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocaleName) { UErrorCode status = U_ZERO_ERROR; ScopedUtfChars localeID(env, javaLocaleName); char maximizedLocaleID[ULOC_FULLNAME_CAPACITY]; uloc_addLikelySubtags(localeID.c_str(), maximizedLocaleID, sizeof(maximizedLocaleID), &status); if (U_FAILURE(status)) { return javaLocaleName; } return env->NewStringUTF(maximizedLocaleID); }
U_NAMESPACE_END // 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); }
// Implemented here because this calls uloc_addLikelySubtags(). U_CAPI UBool U_EXPORT2 uloc_isRightToLeft(const char *locale) { UErrorCode errorCode = U_ZERO_ERROR; char script[8]; int32_t scriptLength = uloc_getScript(locale, script, UPRV_LENGTHOF(script), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || scriptLength == 0) { // Fastpath: We know the likely scripts and their writing direction // for some common languages. errorCode = U_ZERO_ERROR; char lang[8]; int32_t langLength = uloc_getLanguage(locale, lang, UPRV_LENGTHOF(lang), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || langLength == 0) { return FALSE; } const char* langPtr = uprv_strstr(LANG_DIR_STRING, lang); if (langPtr != NULL) { switch (langPtr[langLength]) { case '-': return FALSE; case '+': return TRUE; default: break; // partial match of a longer code } } // Otherwise, find the likely script. errorCode = U_ZERO_ERROR; char likely[ULOC_FULLNAME_CAPACITY]; (void)uloc_addLikelySubtags(locale, likely, UPRV_LENGTHOF(likely), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING) { return FALSE; } scriptLength = uloc_getScript(likely, script, UPRV_LENGTHOF(script), &errorCode); if (U_FAILURE(errorCode) || errorCode == U_STRING_NOT_TERMINATED_WARNING || scriptLength == 0) { return FALSE; } } UScriptCode scriptCode = (UScriptCode)u_getPropertyValueEnum(UCHAR_SCRIPT, script); return uscript_isRightToLeft(scriptCode); }
static int32_t _uloc_minimizeSubtags(const char* localeID, char* minimizedLocaleID, int32_t minimizedLocaleIDCapacity, UErrorCode* err) { /** * ULOC_FULLNAME_CAPACITY will provide enough capacity * that we can build a string that contains the language, * script and region code without worrying about overrunning * the user-supplied buffer. **/ char maximizedTagBuffer[ULOC_FULLNAME_CAPACITY]; int32_t maximizedTagBufferLength = sizeof(maximizedTagBuffer); char lang[ULOC_LANG_CAPACITY]; int32_t langLength = sizeof(lang); char script[ULOC_SCRIPT_CAPACITY]; int32_t scriptLength = sizeof(script); char region[ULOC_COUNTRY_CAPACITY]; int32_t regionLength = sizeof(region); const char* trailing = ""; int32_t trailingLength = 0; int32_t trailingIndex = 0; if(U_FAILURE(*err)) { goto error; } else if (localeID == NULL || minimizedLocaleID == NULL || minimizedLocaleIDCapacity <= 0) { goto error; } trailingIndex = parseTagString( localeID, lang, &langLength, script, &scriptLength, region, ®ionLength, err); if(U_FAILURE(*err)) { /* Overflow indicates an illegal argument error */ if (*err == U_BUFFER_OVERFLOW_ERROR) { *err = U_ILLEGAL_ARGUMENT_ERROR; } goto error; } /* Find the spot where the variants or the keywords begin, if any. */ while (_isIDSeparator(localeID[trailingIndex])) { trailingIndex++; } trailing = &localeID[trailingIndex]; trailingLength = (int32_t)uprv_strlen(trailing); CHECK_TRAILING_VARIANT_SIZE(trailing, trailingLength); createTagString( lang, langLength, script, scriptLength, region, regionLength, NULL, 0, maximizedTagBuffer, maximizedTagBufferLength, err); if(U_FAILURE(*err)) { goto error; } /** * First, we need to first get the maximization * from AddLikelySubtags. **/ maximizedTagBufferLength = uloc_addLikelySubtags( maximizedTagBuffer, maximizedTagBuffer, maximizedTagBufferLength, err); if(U_FAILURE(*err)) { goto error; } /** * Start first with just the language. **/ { char tagBuffer[ULOC_FULLNAME_CAPACITY]; const int32_t tagBufferLength = createLikelySubtagsString( lang, langLength, NULL, 0, NULL, 0, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } else if (uprv_strnicmp( maximizedTagBuffer, tagBuffer, tagBufferLength) == 0) { return createTagString( lang, langLength, NULL, 0, NULL, 0, trailing, trailingLength, minimizedLocaleID, minimizedLocaleIDCapacity, err); } } /** * Next, try the language and region. **/ if (regionLength > 0) { char tagBuffer[ULOC_FULLNAME_CAPACITY]; const int32_t tagBufferLength = createLikelySubtagsString( lang, langLength, NULL, 0, region, regionLength, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } else if (uprv_strnicmp( maximizedTagBuffer, tagBuffer, tagBufferLength) == 0) { return createTagString( lang, langLength, NULL, 0, region, regionLength, trailing, trailingLength, minimizedLocaleID, minimizedLocaleIDCapacity, err); } } /** * Finally, try the language and script. This is our last chance, * since trying with all three subtags would only yield the * maximal version that we already have. **/ if (scriptLength > 0 && regionLength > 0) { char tagBuffer[ULOC_FULLNAME_CAPACITY]; const int32_t tagBufferLength = createLikelySubtagsString( lang, langLength, script, scriptLength, NULL, 0, NULL, 0, tagBuffer, sizeof(tagBuffer), err); if(U_FAILURE(*err)) { goto error; } else if (uprv_strnicmp( maximizedTagBuffer, tagBuffer, tagBufferLength) == 0) { return createTagString( lang, langLength, script, scriptLength, NULL, 0, trailing, trailingLength, minimizedLocaleID, minimizedLocaleIDCapacity, err); } } { /** * If we got here, return the locale ID parameter. **/ const int32_t localeIDLength = (int32_t)uprv_strlen(localeID); uprv_memcpy( minimizedLocaleID, localeID, localeIDLength <= minimizedLocaleIDCapacity ? localeIDLength : minimizedLocaleIDCapacity); return u_terminateChars( minimizedLocaleID, minimizedLocaleIDCapacity, localeIDLength, err); } error: if (!U_FAILURE(*err)) { *err = U_ILLEGAL_ARGUMENT_ERROR; } return -1; }
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] = ""; int32_t locLength = 0; locLength = uloc_addLikelySubtags(locale, loc, sizeof(loc), status); prefRegionLength = uloc_getCountry(loc, prefRegion, sizeof(prefRegion), status); } // Read preferred calendar values from supplementalData calendarPreference UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", status); ures_getByKey(rb, "calendarPreferenceData", rb, status); UResourceBundle *order = ures_getByKey(rb, prefRegion, NULL, status); if (*status == U_MISSING_RESOURCE_ERROR && rb != NULL) { *status = U_ZERO_ERROR; order = ures_getByKey(rb, "001", NULL, status); } // Create a list of calendar type strings UList *values = NULL; if (U_SUCCESS(*status)) { values = ulist_createEmptyList(status); if (U_SUCCESS(*status)) { for (int i = 0; i < ures_getSize(order); i++) { int32_t len; const UChar *type = ures_getStringByIndex(order, i, &len, status); char *caltype = (char*)uprv_malloc(len + 1); if (caltype == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; break; } u_UCharsToChars(type, caltype, len); *(caltype + len) = 0; ulist_addItemEndList(values, caltype, TRUE, status); if (U_FAILURE(*status)) { break; } } if (U_SUCCESS(*status) && !commonlyUsed) { // If not commonlyUsed, add other available values for (int32_t i = 0; CAL_TYPES[i] != NULL; i++) { if (!ulist_containsString(values, CAL_TYPES[i], (int32_t)uprv_strlen(CAL_TYPES[i]))) { ulist_addItemEndList(values, CAL_TYPES[i], FALSE, status); if (U_FAILURE(*status)) { break; } } } } if (U_FAILURE(*status)) { ulist_deleteList(values); values = NULL; } } } ures_close(order); ures_close(rb); if (U_FAILURE(*status) || values == NULL) { return NULL; } // Create string enumeration UEnumeration *en = (UEnumeration*)uprv_malloc(sizeof(UEnumeration)); if (en == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; ulist_deleteList(values); return NULL; } ulist_resetList(values); memcpy(en, &defaultKeywordValues, sizeof(UEnumeration)); en->context = values; return en; }
void TZGNCore::initialize(const Locale& locale, UErrorCode& status) { if (U_FAILURE(status)) { return; } // TimeZoneNames fTimeZoneNames = TimeZoneNames::createInstance(locale, status); if (U_FAILURE(status)) { return; } // Initialize format patterns UnicodeString rpat(TRUE, gDefRegionPattern, -1); UnicodeString fpat(TRUE, gDefFallbackPattern, -1); UErrorCode tmpsts = U_ZERO_ERROR; // OK with fallback warning.. UResourceBundle *zoneStrings = ures_open(U_ICUDATA_ZONE, locale.getName(), &tmpsts); zoneStrings = ures_getByKeyWithFallback(zoneStrings, gZoneStrings, zoneStrings, &tmpsts); if (U_SUCCESS(tmpsts)) { const UChar *regionPattern = ures_getStringByKeyWithFallback(zoneStrings, gRegionFormatTag, NULL, &tmpsts); if (U_SUCCESS(tmpsts) && u_strlen(regionPattern) > 0) { rpat.setTo(regionPattern, -1); } tmpsts = U_ZERO_ERROR; const UChar *fallbackPattern = ures_getStringByKeyWithFallback(zoneStrings, gFallbackFormatTag, NULL, &tmpsts); if (U_SUCCESS(tmpsts) && u_strlen(fallbackPattern) > 0) { fpat.setTo(fallbackPattern, -1); } } ures_close(zoneStrings); fRegionFormat.applyPatternMinMaxArguments(rpat, 1, 1, status); fFallbackFormat.applyPatternMinMaxArguments(fpat, 2, 2, status); if (U_FAILURE(status)) { cleanup(); return; } // locale display names fLocaleDisplayNames = LocaleDisplayNames::createInstance(locale); // hash table for names - no key/value deleters fLocationNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); if (U_FAILURE(status)) { cleanup(); return; } fPartialLocationNamesMap = uhash_open(hashPartialLocationKey, comparePartialLocationKey, NULL, &status); if (U_FAILURE(status)) { cleanup(); return; } uhash_setKeyDeleter(fPartialLocationNamesMap, uprv_free); // no value deleter // target region const char* region = fLocale.getCountry(); int32_t regionLen = uprv_strlen(region); if (regionLen == 0) { char loc[ULOC_FULLNAME_CAPACITY]; uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status); regionLen = uloc_getCountry(loc, fTargetRegion, sizeof(fTargetRegion), &status); if (U_SUCCESS(status)) { fTargetRegion[regionLen] = 0; } else { cleanup(); return; } } else if (regionLen < (int32_t)sizeof(fTargetRegion)) { uprv_strcpy(fTargetRegion, region); } else { fTargetRegion[0] = 0; } // preload generic names for the default zone TimeZone *tz = TimeZone::createDefault(); const UChar *tzID = ZoneMeta::getCanonicalCLDRID(*tz); if (tzID != NULL) { loadStrings(UnicodeString(TRUE, tzID, -1)); } delete tz; }