static void U_CALLCONV initAvailableLocaleList(UErrorCode &status) { U_ASSERT(availableLocaleListCount == 0); U_ASSERT(availableLocaleList == NULL); // for now, there is a hardcoded list, so just walk through that list and set it up. UResourceBundle *index = NULL; UResourceBundle installed; int32_t i = 0; ures_initStackObject(&installed); index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status); ures_getByKey(index, "InstalledLocales", &installed, &status); if(U_SUCCESS(status)) { availableLocaleListCount = ures_getSize(&installed); availableLocaleList = new Locale[availableLocaleListCount]; if (availableLocaleList != NULL) { ures_resetIterator(&installed); while(ures_hasNext(&installed)) { const char *tempKey = NULL; ures_getNextString(&installed, NULL, &tempKey, &status); availableLocaleList[i++] = Locale(tempKey); } } U_ASSERT(availableLocaleListCount == i); ures_close(&installed); } ures_close(index); ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); }
UnicodeString& U_EXPORT2 ZoneMeta::getSingleCountry(const UnicodeString &tzid, UnicodeString &country) { UErrorCode status = U_ZERO_ERROR; // Get canonical country for the zone getCanonicalCountry(tzid, country); if (!country.isEmpty()) { UResourceBundle *supplementalDataBundle = ures_openDirect(NULL, gSupplementalData, &status); UResourceBundle *zoneFormatting = ures_getByKey(supplementalDataBundle, gZoneFormattingTag, NULL, &status); UResourceBundle *multizone = ures_getByKey(zoneFormatting, gMultizoneTag, NULL, &status); if (U_SUCCESS(status)) { while (ures_hasNext(multizone)) { int32_t len; const UChar* multizoneCountry = ures_getNextString(multizone, &len, NULL, &status); if (country.compare(multizoneCountry, len) == 0) { // Included in the multizone country list country.remove(); break; } } } ures_close(multizone); ures_close(zoneFormatting); ures_close(supplementalDataBundle); } return country; }
static UBool isAvailableLocaleListInitialized(UErrorCode &status) { // for now, there is a hardcoded list, so just walk through that list and set it up. UBool needInit; UMTX_CHECK(NULL, availableLocaleList == NULL, needInit); if (needInit) { UResourceBundle *index = NULL; UResourceBundle installed; Locale * temp; int32_t i = 0; int32_t localeCount; ures_initStackObject(&installed); index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status); ures_getByKey(index, "InstalledLocales", &installed, &status); if(U_SUCCESS(status)) { localeCount = ures_getSize(&installed); temp = new Locale[localeCount]; if (temp != NULL) { ures_resetIterator(&installed); while(ures_hasNext(&installed)) { const char *tempKey = NULL; ures_getNextString(&installed, NULL, &tempKey, &status); temp[i++] = Locale(tempKey); } umtx_lock(NULL); if (availableLocaleList == NULL) { availableLocaleListCount = localeCount; availableLocaleList = temp; temp = NULL; ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup); } umtx_unlock(NULL); needInit = FALSE; if (temp) { delete []temp; } } ures_close(&installed); } ures_close(index); } return !needInit; }
UnicodeString ResourceBundle::getNextString(const char ** key, UErrorCode& status) { int32_t len = 0; const UChar* r = ures_getNextString(fResource, &len, key, &status); return UnicodeString(TRUE, r, len); }
UHashtable* ZoneMeta::createCanonicalMap(void) { UErrorCode status = U_ZERO_ERROR; UHashtable *canonicalMap = NULL; UResourceBundle *zoneFormatting = NULL; UResourceBundle *tzitem = NULL; UResourceBundle *aliases = NULL; StringEnumeration* tzenum = NULL; int32_t numZones; canonicalMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); if (U_FAILURE(status)) { return NULL; } // no key deleter uhash_setValueDeleter(canonicalMap, deleteCanonicalMapEntry); zoneFormatting = ures_openDirect(NULL, gSupplementalData, &status); zoneFormatting = ures_getByKey(zoneFormatting, gZoneFormattingTag, zoneFormatting, &status); if (U_FAILURE(status)) { goto error_cleanup; } while (ures_hasNext(zoneFormatting)) { tzitem = ures_getNextResource(zoneFormatting, tzitem, &status); if (U_FAILURE(status)) { status = U_ZERO_ERROR; continue; } if (ures_getType(tzitem) != URES_TABLE) { continue; } int32_t canonicalLen; const UChar *canonical = ures_getStringByKey(tzitem, gCanonicalTag, &canonicalLen, &status); if (U_FAILURE(status)) { status = U_ZERO_ERROR; continue; } int32_t territoryLen; const UChar *territory = ures_getStringByKey(tzitem, gTerritoryTag, &territoryLen, &status); if (U_FAILURE(status)) { territory = NULL; status = U_ZERO_ERROR; } // Create canonical map entry CanonicalMapEntry *entry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry)); if (entry == NULL) { status = U_MEMORY_ALLOCATION_ERROR; goto error_cleanup; } entry->id = canonical; if (territory == NULL || u_strcmp(territory, gWorld) == 0) { entry->country = NULL; } else { entry->country = territory; } // Put this entry in the hashtable. Since this hashtable has no key deleter, // key is treated as const, but must be passed as non-const. uhash_put(canonicalMap, (UChar*)canonical, entry, &status); if (U_FAILURE(status)) { goto error_cleanup; } // Get aliases aliases = ures_getByKey(tzitem, gAliasesTag, aliases, &status); if (U_FAILURE(status)) { // No aliases status = U_ZERO_ERROR; continue; } while (ures_hasNext(aliases)) { const UChar* alias = ures_getNextString(aliases, NULL, NULL, &status); if (U_FAILURE(status)) { status = U_ZERO_ERROR; continue; } // Create canonical map entry for this alias entry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry)); if (entry == NULL) { status = U_MEMORY_ALLOCATION_ERROR; goto error_cleanup; } entry->id = canonical; if (territory == NULL || u_strcmp(territory, gWorld) == 0) { entry->country = NULL; } else { entry->country = territory; } // Put this entry in the hashtable. Since this hashtable has no key deleter, // key is treated as const, but must be passed as non-const. uhash_put(canonicalMap, (UChar*)alias, entry, &status); if (U_FAILURE(status)) { goto error_cleanup; } } } // Some available Olson zones are not included in CLDR data (such as Asia/Riyadh87). // Also, when we update Olson tzdata, new zones may be added. // This code scans all available zones in zoneinfo.res, and if any of them are // missing, add them to the map. tzenum = TimeZone::createEnumeration(); numZones = tzenum->count(status); if (U_SUCCESS(status)) { int32_t i; for (i = 0; i < numZones; i++) { const UnicodeString *zone = tzenum->snext(status); if (U_FAILURE(status)) { // We should not get here. status = U_ZERO_ERROR; continue; } UChar zoneUChars[ZID_KEY_MAX]; int32_t zoneUCharsLen = zone->extract(zoneUChars, ZID_KEY_MAX, status) + 1; // Add one for NUL termination if (U_FAILURE(status) || status==U_STRING_NOT_TERMINATED_WARNING) { status = U_ZERO_ERROR; continue; // zone id is too long to extract } CanonicalMapEntry *entry = (CanonicalMapEntry*)uhash_get(canonicalMap, zoneUChars); if (entry) { // Already included in CLDR data continue; } // Not in CLDR data, but it could be new one whose alias is available // in CLDR. int32_t nTzdataEquivalent = TimeZone::countEquivalentIDs(*zone); int32_t j; for (j = 0; j < nTzdataEquivalent; j++) { UnicodeString alias = TimeZone::getEquivalentID(*zone, j); if (alias == *zone) { continue; } UChar aliasUChars[ZID_KEY_MAX]; alias.extract(aliasUChars, ZID_KEY_MAX, status); if (U_FAILURE(status) || status==U_STRING_NOT_TERMINATED_WARNING) { status = U_ZERO_ERROR; continue; // zone id is too long to extract } entry = (CanonicalMapEntry*)uhash_get(canonicalMap, aliasUChars); if (entry != NULL) { break; } } // Create a new map entry CanonicalMapEntry* newEntry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry)); int32_t idLen; if (newEntry == NULL) { status = U_MEMORY_ALLOCATION_ERROR; goto error_cleanup; } if (entry == NULL) { // Set dereferenced zone ID as the canonical ID UnicodeString derefZone; TimeZone::dereferOlsonLink(*zone, derefZone); if (derefZone.length() == 0) { // It should never happen.. but just in case derefZone = *zone; } idLen = derefZone.length() + 1; newEntry->id = allocUStringInTable(idLen); if (newEntry->id == NULL) { status = U_MEMORY_ALLOCATION_ERROR; uprv_free(newEntry); goto error_cleanup; } // Copy NULL terminated string derefZone.extract((UChar*)(newEntry->id), idLen, status); if (U_FAILURE(status)) { removeLastUStringFromTable(); uprv_free(newEntry); goto error_cleanup; } // No territory information available newEntry->country = NULL; } else { // Duplicate the entry newEntry->id = entry->id; newEntry->country = entry->country; } // Put this entry in the hashtable UChar *key = allocUStringInTable(zoneUCharsLen); if (key == NULL) { status = U_MEMORY_ALLOCATION_ERROR; deleteCanonicalMapEntry(newEntry); goto error_cleanup; } u_strncpy(key, zoneUChars, zoneUCharsLen); uhash_put(canonicalMap, key, newEntry, &status); if (U_FAILURE(status)) { goto error_cleanup; } } } normal_cleanup: ures_close(aliases); ures_close(tzitem); ures_close(zoneFormatting); delete tzenum; return canonicalMap; error_cleanup: if (canonicalMap != NULL) { uhash_close(canonicalMap); canonicalMap = NULL; } goto normal_cleanup; }
UnicodeString PluralRules::getRuleFromResource(const Locale& locale, UPluralType type, UErrorCode& errCode) { UnicodeString emptyStr; if (U_FAILURE(errCode)) { return emptyStr; } LocalUResourceBundlePointer rb(ures_openDirect(NULL, "plurals", &errCode)); if(U_FAILURE(errCode)) { return emptyStr; } const char *typeKey; switch (type) { case UPLURAL_TYPE_CARDINAL: typeKey = "locales"; break; case UPLURAL_TYPE_ORDINAL: typeKey = "locales_ordinals"; break; default: // Must not occur: The caller should have checked for valid types. errCode = U_ILLEGAL_ARGUMENT_ERROR; return emptyStr; } LocalUResourceBundlePointer locRes(ures_getByKey(rb.getAlias(), typeKey, NULL, &errCode)); if(U_FAILURE(errCode)) { return emptyStr; } int32_t resLen=0; const char *curLocaleName=locale.getName(); const UChar* s = ures_getStringByKey(locRes.getAlias(), curLocaleName, &resLen, &errCode); if (s == NULL) { // Check parent locales. UErrorCode status = U_ZERO_ERROR; char parentLocaleName[ULOC_FULLNAME_CAPACITY]; const char *curLocaleName=locale.getName(); uprv_strcpy(parentLocaleName, curLocaleName); while (uloc_getParent(parentLocaleName, parentLocaleName, ULOC_FULLNAME_CAPACITY, &status) > 0) { resLen=0; s = ures_getStringByKey(locRes.getAlias(), parentLocaleName, &resLen, &status); if (s != NULL) { errCode = U_ZERO_ERROR; break; } status = U_ZERO_ERROR; } } if (s==NULL) { return emptyStr; } char setKey[256]; UChar result[256]; u_UCharsToChars(s, setKey, resLen + 1); // printf("\n PluralRule: %s\n", setKey); LocalUResourceBundlePointer ruleRes(ures_getByKey(rb.getAlias(), "rules", NULL, &errCode)); if(U_FAILURE(errCode)) { return emptyStr; } resLen=0; LocalUResourceBundlePointer setRes(ures_getByKey(ruleRes.getAlias(), setKey, NULL, &errCode)); if (U_FAILURE(errCode)) { return emptyStr; } int32_t numberKeys = ures_getSize(setRes.getAlias()); char *key=NULL; int32_t len=0; for(int32_t i=0; i<numberKeys; ++i) { int32_t keyLen; resLen=0; s=ures_getNextString(setRes.getAlias(), &resLen, (const char**)&key, &errCode); keyLen = (int32_t)uprv_strlen(key); u_charsToUChars(key, result+len, keyLen); len += keyLen; result[len++]=COLON; uprv_memcpy(result+len, s, resLen*sizeof(UChar)); len += resLen; result[len++]=SEMI_COLON; } result[len++]=0; u_UCharsToChars(result, setKey, len); // printf(" Rule: %s\n", setKey); return UnicodeString(result); }
void TimeUnitFormat::readFromCurrentLocale(EStyle style, const char* key, UErrorCode& err) { if (U_FAILURE(err)) { return; } // fill timeUnitToCountToPatterns from resource file // err is used to indicate wrong status except missing resource. // status is an error code used in resource lookup. // status does not affect "err". UErrorCode status = U_ZERO_ERROR; UResourceBundle *rb, *unitsRes; rb = ures_open(NULL, fLocale.getName(), &status); unitsRes = ures_getByKey(rb, key, NULL, &status); if (U_FAILURE(status)) { ures_close(unitsRes); ures_close(rb); return; } int32_t size = ures_getSize(unitsRes); for ( int32_t index = 0; index < size; ++index) { // resource of one time unit UResourceBundle* oneTimeUnit = ures_getByIndex(unitsRes, index, NULL, &status); if (U_SUCCESS(status)) { const char* timeUnitName = ures_getKey(oneTimeUnit); if (timeUnitName == NULL) { ures_close(oneTimeUnit); continue; } UResourceBundle* countsToPatternRB = ures_getByKey(unitsRes, timeUnitName, NULL, &status); if (countsToPatternRB == NULL || U_FAILURE(status)) { ures_close(countsToPatternRB); ures_close(oneTimeUnit); continue; } TimeUnit::UTimeUnitFields timeUnitField = TimeUnit::UTIMEUNIT_FIELD_COUNT; if ( uprv_strcmp(timeUnitName, gTimeUnitYear) == 0 ) { timeUnitField = TimeUnit::UTIMEUNIT_YEAR; } else if ( uprv_strcmp(timeUnitName, gTimeUnitMonth) == 0 ) { timeUnitField = TimeUnit::UTIMEUNIT_MONTH; } else if ( uprv_strcmp(timeUnitName, gTimeUnitDay) == 0 ) { timeUnitField = TimeUnit::UTIMEUNIT_DAY; } else if ( uprv_strcmp(timeUnitName, gTimeUnitHour) == 0 ) { timeUnitField = TimeUnit::UTIMEUNIT_HOUR; } else if ( uprv_strcmp(timeUnitName, gTimeUnitMinute) == 0 ) { timeUnitField = TimeUnit::UTIMEUNIT_MINUTE; } else if ( uprv_strcmp(timeUnitName, gTimeUnitSecond) == 0 ) { timeUnitField = TimeUnit::UTIMEUNIT_SECOND; } else if ( uprv_strcmp(timeUnitName, gTimeUnitWeek) == 0 ) { timeUnitField = TimeUnit::UTIMEUNIT_WEEK; } else { ures_close(countsToPatternRB); ures_close(oneTimeUnit); continue; } Hashtable* countToPatterns = fTimeUnitToCountToPatterns[timeUnitField]; if (countToPatterns == NULL) { countToPatterns = initHash(err); if (U_FAILURE(err)) { ures_close(countsToPatternRB); ures_close(oneTimeUnit); delete countToPatterns; break; } } int32_t count = ures_getSize(countsToPatternRB); const UChar* pattern; const char* pluralCount; int32_t ptLength; for ( int32_t pluralIndex = 0; pluralIndex < count; ++pluralIndex) { // resource of count to pattern pattern = ures_getNextString(countsToPatternRB, &ptLength, &pluralCount, &status); if (U_FAILURE(status)) { continue; } MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err); if ( U_SUCCESS(err) ) { if (fNumberFormat != NULL) { messageFormat->setFormat(0, *fNumberFormat); } MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCount); if (formatters == NULL) { formatters = (MessageFormat**)uprv_malloc(kTotal*sizeof(MessageFormat*)); formatters[kFull] = NULL; formatters[kAbbreviate] = NULL; countToPatterns->put(pluralCount, formatters, err); if (U_FAILURE(err)) { uprv_free(formatters); } } if (U_SUCCESS(err)) { //delete formatters[style]; formatters[style] = messageFormat; } } if (U_FAILURE(err)) { ures_close(countsToPatternRB); ures_close(oneTimeUnit); ures_close(unitsRes); ures_close(rb); delete messageFormat; delete countToPatterns; return; } } if (fTimeUnitToCountToPatterns[timeUnitField] == NULL) { fTimeUnitToCountToPatterns[timeUnitField] = countToPatterns; } ures_close(countsToPatternRB); } ures_close(oneTimeUnit); } ures_close(unitsRes); ures_close(rb); }
RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status) : ruleSets(NULL) , defaultRuleSet(NULL) , locale(alocale) , collator(NULL) , decimalFormatSymbols(NULL) , lenient(FALSE) , lenientParseRules(NULL) , localizations(NULL) { if (U_FAILURE(status)) { return; } const char* rules_tag = "RBNFRules"; const char* fmt_tag = ""; switch (tag) { case URBNF_SPELLOUT: fmt_tag = "SpelloutRules"; break; case URBNF_ORDINAL: fmt_tag = "OrdinalRules"; break; case URBNF_DURATION: fmt_tag = "DurationRules"; break; case URBNF_NUMBERING_SYSTEM: fmt_tag = "NumberingSystemRules"; break; default: status = U_ILLEGAL_ARGUMENT_ERROR; return; } // TODO: read localization info from resource LocalizationInfo* locinfo = NULL; int32_t len = 0; UResourceBundle* nfrb = ures_open(U_ICUDATA_RBNF, locale.getName(), &status); if (U_SUCCESS(status)) { setLocaleIDs(ures_getLocaleByType(nfrb, ULOC_VALID_LOCALE, &status), ures_getLocaleByType(nfrb, ULOC_ACTUAL_LOCALE, &status)); UResourceBundle* rbnfRules = ures_getByKeyWithFallback(nfrb, rules_tag, NULL, &status); if (U_FAILURE(status)) { ures_close(nfrb); } UResourceBundle* ruleSets = ures_getByKeyWithFallback(rbnfRules, fmt_tag, NULL, &status); if (U_FAILURE(status)) { ures_close(rbnfRules); ures_close(nfrb); return; } UnicodeString desc; while (ures_hasNext(ruleSets)) { const UChar* currentString = ures_getNextString(ruleSets,&len,NULL,&status); desc.append(currentString); } UParseError perror; init (desc, locinfo, perror, status); //TODO: we need a real fix - see #6895 / #6896 noParse = FALSE; if (tag == URBNF_SPELLOUT) { const char *lang = alocale.getLanguage(); for (int32_t i = 0; NO_SPELLOUT_PARSE_LANGUAGES[i] != NULL; i++) { if (uprv_strcmp(lang, NO_SPELLOUT_PARSE_LANGUAGES[i]) == 0) { noParse = TRUE; break; } } } //TODO: end ures_close(ruleSets); ures_close(rbnfRules); } ures_close(nfrb); }