void CalendarData::initData(const char *locale, const char *type, UErrorCode& status) { fOtherFillin = ures_open(U_CALENDAR_DATA, locale, &status); fFillin = ures_getByKey(fOtherFillin, U_CALENDAR_KEY, fFillin, &status); if((type != NULL) && (*type != '\0') && (uprv_strcmp(type, U_GREGORIAN_KEY))) { fBundle = ures_getByKeyWithFallback(fFillin, type, NULL, &status); fFallback = ures_getByKeyWithFallback(fFillin, U_GREGORIAN_KEY, NULL, &status); #if defined (U_DEBUG_CALDATA) fprintf(stderr, "%p: CalendarData(%s, %s, %s) -> main(%p, %s)=%s, fallback(%p, %s)=%s\n", this, locale, type, u_errorName(status), fBundle, type, fBundle?ures_getLocale(fBundle, &status):"", fFallback, U_GREGORIAN_KEY, fFallback?ures_getLocale(fFallback, &status):""); #endif } else { fBundle = ures_getByKeyWithFallback(fFillin, U_GREGORIAN_KEY, NULL, &status); #if defined (U_DEBUG_CALDATA) fprintf(stderr, "%p: CalendarData(%s, %s, %s) -> main(%p, %s)=%s, fallback = NULL\n", this, locale, type, u_errorName(status), fBundle, U_GREGORIAN_KEY, fBundle?ures_getLocale(fBundle, &status):"" ); #endif } }
static ListFormatInternal* loadListFormatInternal( const Locale& locale, const char * style, UErrorCode& errorCode) { UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode); if (U_FAILURE(errorCode)) { ures_close(rb); return NULL; } rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode); rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode); if (U_FAILURE(errorCode)) { ures_close(rb); return NULL; } UnicodeString two, start, middle, end; getStringByKey(rb, "2", two, errorCode); getStringByKey(rb, "start", start, errorCode); getStringByKey(rb, "middle", middle, errorCode); getStringByKey(rb, "end", end, errorCode); ures_close(rb); if (U_FAILURE(errorCode)) { return NULL; } ListFormatInternal* result = new ListFormatInternal(two, start, middle, end, errorCode); if (result == NULL) { errorCode = U_MEMORY_ALLOCATION_ERROR; return NULL; } if (U_FAILURE(errorCode)) { delete result; return NULL; } return result; }
U_CAPI void U_EXPORT2 ucol_prepareShortStringOpen( const char *definition, UBool, UParseError *parseError, UErrorCode *status) { if(U_FAILURE(*status)) return; UParseError internalParseError; if(!parseError) { parseError = &internalParseError; } parseError->line = 0; parseError->offset = 0; parseError->preContext[0] = 0; parseError->postContext[0] = 0; // first we want to pick stuff out of short string. // we'll end up with an UCA version, locale and a bunch of // settings // analyse the string in order to get everything we need. CollatorSpec s; ucol_sit_initCollatorSpecs(&s); ucol_sit_readSpecs(&s, definition, parseError, status); ucol_sit_calculateWholeLocale(&s); char buffer[internalBufferSize]; uprv_memset(buffer, 0, internalBufferSize); uloc_canonicalize(s.locale, buffer, internalBufferSize, status); UResourceBundle *b = ures_open(U_ICUDATA_COLL, buffer, status); /* we try to find stuff from keyword */ UResourceBundle *collations = ures_getByKey(b, "collations", NULL, status); UResourceBundle *collElem = NULL; char keyBuffer[256]; // if there is a keyword, we pick it up and try to get elements if(!uloc_getKeywordValue(buffer, "collation", keyBuffer, 256, status)) { // no keyword. we try to find the default setting, which will give us the keyword value UResourceBundle *defaultColl = ures_getByKeyWithFallback(collations, "default", NULL, status); if(U_SUCCESS(*status)) { int32_t defaultKeyLen = 0; const UChar *defaultKey = ures_getString(defaultColl, &defaultKeyLen, status); u_UCharsToChars(defaultKey, keyBuffer, defaultKeyLen); keyBuffer[defaultKeyLen] = 0; } else { *status = U_INTERNAL_PROGRAM_ERROR; return; } ures_close(defaultColl); } collElem = ures_getByKeyWithFallback(collations, keyBuffer, collElem, status); ures_close(collElem); ures_close(collations); ures_close(b); }
RuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status) : ruleSets(NULL) , ruleSetDescriptions(NULL) , numRuleSets(0) , 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; 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)) { desc.append(ures_getNextUnicodeString(ruleSets,NULL,&status)); } UParseError perror; init (desc, locinfo, perror, status); ures_close(ruleSets); ures_close(rbnfRules); } ures_close(nfrb); }
const CompactTrieDictionary * ICULanguageBreakFactory::loadDictionaryFor(UScriptCode script, int32_t /*breakType*/) { UErrorCode status = U_ZERO_ERROR; // Open root from brkitr tree. char dictnbuff[256]; char ext[4]={'\0'}; UResourceBundle *b = ures_open(U_ICUDATA_BRKITR, "", &status); b = ures_getByKeyWithFallback(b, "dictionaries", b, &status); b = ures_getByKeyWithFallback(b, uscript_getShortName(script), b, &status); int32_t dictnlength = 0; const UChar *dictfname = ures_getString(b, &dictnlength, &status); if (U_SUCCESS(status) && (size_t)dictnlength >= sizeof(dictnbuff)) { dictnlength = 0; status = U_BUFFER_OVERFLOW_ERROR; } if (U_SUCCESS(status) && dictfname) { UChar* extStart=u_strchr(dictfname, 0x002e); int len = 0; if(extStart!=NULL){ len = extStart-dictfname; u_UCharsToChars(extStart+1, ext, sizeof(ext)); // nul terminates the buff u_UCharsToChars(dictfname, dictnbuff, len); } dictnbuff[len]=0; // nul terminate } ures_close(b); UDataMemory *file = udata_open(U_ICUDATA_BRKITR, ext, dictnbuff, &status); if (U_SUCCESS(status)) { const CompactTrieDictionary *dict = new CompactTrieDictionary( file, status); if (U_SUCCESS(status) && dict == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } if (U_FAILURE(status)) { delete dict; dict = NULL; } return dict; } else if (dictfname != NULL){ //create dummy dict if dictionary filename not valid UChar c = 0x0020; status = U_ZERO_ERROR; MutableTrieDictionary *mtd = new MutableTrieDictionary(c, status, TRUE); mtd->addWord(&c, 1, status, 1); return new CompactTrieDictionary(*mtd, status); } return NULL; }
// tryGetByKeyWithFallback returns a sub-resource bundle that matches given // criteria or NULL if none found. rb is the resource bundle that we are // searching. If rb == NULL then this function behaves as if no sub-resource // is found; path is the key of the sub-resource, // (i.e "foo" but not "foo/bar"); If fillIn is NULL, caller must always call // ures_close() on returned resource. See below for example when fillIn is // not NULL. flags is ANY or NOT_ROOT. Optionally, these values // can be ored with MUST. MUST by itself is the same as ANY | MUST. // The locale of the returned sub-resource will either match the // flags or the returned sub-resouce will be NULL. If MUST is included in // flags, and not suitable sub-resource is found then in addition to returning // NULL, this function also sets status to U_MISSING_RESOURCE_ERROR. If MUST // is not included in flags, then this function just returns NULL if no // such sub-resource is found and will never set status to // U_MISSING_RESOURCE_ERROR. // // Example: This code first searches for "foo/bar" sub-resource without falling // back to ROOT. Then searches for "baz" sub-resource as last resort. // // UResourcebundle* fillIn = NULL; // UResourceBundle* data = tryGetByKeyWithFallback(rb, "foo", &fillIn, NON_ROOT, status); // data = tryGetByKeyWithFallback(data, "bar", &fillIn, NON_ROOT, status); // if (!data) { // data = tryGetbyKeyWithFallback(rb, "baz", &fillIn, MUST, status); // } // if (U_FAILURE(status)) { // ures_close(fillIn); // return; // } // doStuffWithNonNullSubresource(data); // // /* Wrong! don't do the following as it can leak memory if fillIn gets set // to NULL. */ // fillIn = tryGetByKeyWithFallback(rb, "wrong", &fillIn, ANY, status); // // ures_close(fillIn); // static UResourceBundle* tryGetByKeyWithFallback(const UResourceBundle* rb, const char* path, UResourceBundle** fillIn, FallbackFlags flags, UErrorCode& status) { if (U_FAILURE(status)) { return NULL; } UBool must = (flags & MUST); if (rb == NULL) { if (must) { status = U_MISSING_RESOURCE_ERROR; } return NULL; } UResourceBundle* result = NULL; UResourceBundle* ownedByUs = NULL; if (fillIn == NULL) { ownedByUs = ures_getByKeyWithFallback(rb, path, NULL, &status); result = ownedByUs; } else { *fillIn = ures_getByKeyWithFallback(rb, path, *fillIn, &status); result = *fillIn; } if (U_FAILURE(status)) { ures_close(ownedByUs); if (status == U_MISSING_RESOURCE_ERROR && !must) { status = U_ZERO_ERROR; } return NULL; } flags = (FallbackFlags) (flags & ~MUST); switch (flags) { case NOT_ROOT: { UBool bRoot = isRoot(result, status); if (bRoot || U_FAILURE(status)) { ures_close(ownedByUs); if (must && (status == U_ZERO_ERROR)) { status = U_MISSING_RESOURCE_ERROR; } return NULL; } return result; } case ANY: return result; default: ures_close(ownedByUs); status = U_ILLEGAL_ARGUMENT_ERROR; return NULL; } }
static UnicodeString loadNumericDateFormatterPattern( const UResourceBundle *resource, const char *pattern, UErrorCode &status) { UnicodeString result; if (U_FAILURE(status)) { return result; } CharString chs; chs.append("durationUnits", status) .append("/", status).append(pattern, status); LocalUResourceBundlePointer patternBundle( ures_getByKeyWithFallback( resource, chs.data(), NULL, &status)); if (U_FAILURE(status)) { return result; } getString(patternBundle.getAlias(), result, status); // Replace 'h' with 'H' int32_t len = result.length(); UChar *buffer = result.getBuffer(len); for (int32_t i = 0; i < len; ++i) { if (buffer[i] == 0x68) { // 'h' buffer[i] = 0x48; // 'H' } } result.releaseBuffer(len); return result; }
U_CAPI void U_EXPORT2 ulocdata_getPaperSize(const char* localeID, int32_t *height, int32_t *width, UErrorCode *status){ UResourceBundle* bundle=NULL; UResourceBundle* paperSizeBundle = NULL; const int32_t* paperSize=NULL; int32_t len = 0; if(status == NULL || U_FAILURE(*status)){ return; } bundle = measurementDataBundleForLocale(localeID, status); paperSizeBundle = ures_getByKeyWithFallback(bundle, PAPER_SIZE, NULL, status); paperSize = ures_getIntVector(paperSizeBundle, &len, status); if(U_SUCCESS(*status)){ if(len < 2){ *status = U_INTERNAL_PROGRAM_ERROR; }else{ *height = paperSize[0]; *width = paperSize[1]; } } ures_close(bundle); ures_close(paperSizeBundle); }
// initCDFLocaleData initializes result with data from CLDR. // inLocale is the locale, the CLDR data is stored in result. // We load the UNUM_SHORT and UNUM_LONG data looking first in local numbering // system and not including root locale in fallback. Next we try in the latn // numbering system where we fallback all the way to root. If we don't find // UNUM_SHORT data in these three places, we report an error. If we find // UNUM_SHORT data before finding UNUM_LONG data we make UNUM_LONG data fall // back to UNUM_SHORT data. static void initCDFLocaleData(const Locale& inLocale, CDFLocaleData* result, UErrorCode& status) { LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(inLocale, status)); if (U_FAILURE(status)) { return; } const char* numberingSystemName = ns->getName(); UResourceBundle* rb = ures_open(NULL, inLocale.getName(), &status); rb = ures_getByKeyWithFallback(rb, gNumberElementsTag, rb, &status); if (U_FAILURE(status)) { ures_close(rb); return; } UResourceBundle* shortDataFillIn = NULL; UResourceBundle* longDataFillIn = NULL; UResourceBundle* shortData = NULL; UResourceBundle* longData = NULL; if (uprv_strcmp(numberingSystemName, gLatnTag) != 0) { LocalUResourceBundlePointer localResource( tryGetByKeyWithFallback(rb, numberingSystemName, NULL, NOT_ROOT, status)); shortData = tryGetDecimalFallback( localResource.getAlias(), gPatternsShort, &shortDataFillIn, NOT_ROOT, status); longData = tryGetDecimalFallback( localResource.getAlias(), gPatternsLong, &longDataFillIn, NOT_ROOT, status); } if (U_FAILURE(status)) { ures_close(shortDataFillIn); ures_close(longDataFillIn); ures_close(rb); return; } // If we haven't found UNUM_SHORT look in latn numbering system. We must // succeed at finding UNUM_SHORT here. if (shortData == NULL) { LocalUResourceBundlePointer latnResource(tryGetByKeyWithFallback(rb, gLatnTag, NULL, MUST, status)); shortData = tryGetDecimalFallback(latnResource.getAlias(), gPatternsShort, &shortDataFillIn, MUST, status); if (longData == NULL) { longData = tryGetDecimalFallback(latnResource.getAlias(), gPatternsLong, &longDataFillIn, ANY, status); if (longData != NULL && isRoot(longData, status) && !isRoot(shortData, status)) { longData = NULL; } } } initCDFLocaleStyleData(shortData, &result->shortData, status); ures_close(shortDataFillIn); if (U_FAILURE(status)) { ures_close(longDataFillIn); ures_close(rb); } if (longData == NULL) { result->longData.setToBogus(); } else { initCDFLocaleStyleData(longData, &result->longData, status); } ures_close(longDataFillIn); ures_close(rb); }
ResourceBundle ResourceBundle::getWithFallback(const char* key, UErrorCode& status){ UResourceBundle r; ures_initStackObject(&r); ures_getByKeyWithFallback(fResource, key, &r, &status); ResourceBundle res(&r, status); if(U_SUCCESS(status)){ ures_close(&r); } return res; }
DictionaryMatcher * ICULanguageBreakFactory::loadDictionaryMatcherFor(UScriptCode script, int32_t /* brkType */) { UErrorCode status = U_ZERO_ERROR; // open root from brkitr tree. UResourceBundle *b = ures_open(U_ICUDATA_BRKITR, "", &status); b = ures_getByKeyWithFallback(b, "dictionaries", b, &status); int32_t dictnlength = 0; const UChar *dictfname = ures_getStringByKeyWithFallback(b, uscript_getShortName(script), &dictnlength, &status); if (U_FAILURE(status)) { ures_close(b); return NULL; } CharString dictnbuf; CharString ext; const UChar *extStart = u_memrchr(dictfname, 0x002e, dictnlength); // last dot if (extStart != NULL) { int32_t len = (int32_t)(extStart - dictfname); ext.appendInvariantChars(UnicodeString(FALSE, extStart + 1, dictnlength - len - 1), status); dictnlength = len; } dictnbuf.appendInvariantChars(UnicodeString(FALSE, dictfname, dictnlength), status); ures_close(b); UDataMemory *file = udata_open(U_ICUDATA_BRKITR, ext.data(), dictnbuf.data(), &status); if (U_SUCCESS(status)) { // build trie const uint8_t *data = (const uint8_t *)udata_getMemory(file); const int32_t *indexes = (const int32_t *)data; const int32_t offset = indexes[DictionaryData::IX_STRING_TRIE_OFFSET]; const int32_t trieType = indexes[DictionaryData::IX_TRIE_TYPE] & DictionaryData::TRIE_TYPE_MASK; DictionaryMatcher *m = NULL; if (trieType == DictionaryData::TRIE_TYPE_BYTES) { const int32_t transform = indexes[DictionaryData::IX_TRANSFORM]; const char *characters = (const char *)(data + offset); m = new BytesDictionaryMatcher(characters, transform, file); } else if (trieType == DictionaryData::TRIE_TYPE_UCHARS) { const UChar *characters = (const UChar *)(data + offset); m = new UCharsDictionaryMatcher(characters, file); } if (m == NULL) { // no matcher exists to take ownership - either we are an invalid // type or memory allocation failed udata_close(file); } return m; } else if (dictfname != NULL) { // we don't have a dictionary matcher. // returning NULL here will cause us to fail to find a dictionary break engine, as expected status = U_ZERO_ERROR; return NULL; } return NULL; }
void RelativeDateFormat::initCapitalizationContextInfo(const Locale& thelocale) { #if !UCONFIG_NO_BREAK_ITERATION const char * localeID = (thelocale != NULL)? thelocale.getBaseName(): NULL; UErrorCode status = U_ZERO_ERROR; UResourceBundle *rb = ures_open(NULL, localeID, &status); rb = ures_getByKeyWithFallback(rb, "contextTransforms", rb, &status); rb = ures_getByKeyWithFallback(rb, "relative", rb, &status); if (U_SUCCESS(status) && rb != NULL) { int32_t len = 0; const int32_t * intVector = ures_getIntVector(rb, &len, &status); if (U_SUCCESS(status) && intVector != NULL && len >= 2) { fCapitalizationOfRelativeUnitsForUIListMenu = intVector[0]; fCapitalizationOfRelativeUnitsForStandAlone = intVector[1]; } } ures_close(rb); #endif }
UResourceBundle* CalendarData::getByKey(const char *key, UErrorCode& status) { if(U_FAILURE(status)) { return NULL; } if(fBundle) { fFillin = ures_getByKeyWithFallback(fBundle, key, fFillin, &status); #if defined (U_DEBUG_CALDATA) fprintf(stderr, "%p: get %s -> %s - from MAIN %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status)); #endif } if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) { status = U_ZERO_ERROR; // retry with fallback (gregorian) fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status); #if defined (U_DEBUG_CALDATA) fprintf(stderr, "%p: get %s -> %s - from FALLBACK %s\n",this, key, u_errorName(status), ures_getLocale(fFillin, &status)); #endif } return fFillin; }
TZNames* TZNames::createInstance(UResourceBundle* rb, const char* key, const UnicodeString& tzID) { if (rb == NULL || key == NULL || *key == 0) { return NULL; } const UChar** names = loadData(rb, key); const UChar* locationName = NULL; UChar* locationNameOwned = NULL; UErrorCode status = U_ZERO_ERROR; int32_t len = 0; UResourceBundle* table = ures_getByKeyWithFallback(rb, key, NULL, &status); locationName = ures_getStringByKeyWithFallback(table, gEcTag, &len, &status); // ignore missing resource here status = U_ZERO_ERROR; ures_close(table); if (locationName == NULL) { UnicodeString tmpName; int32_t tmpNameLen = 0; TimeZoneNamesImpl::getDefaultExemplarLocationName(tzID, tmpName); tmpNameLen = tmpName.length(); if (tmpNameLen > 0) { locationNameOwned = (UChar*) uprv_malloc(sizeof(UChar) * (tmpNameLen + 1)); if (locationNameOwned) { tmpName.extract(locationNameOwned, tmpNameLen + 1, status); locationName = locationNameOwned; } } } TZNames* tznames = NULL; if (locationName != NULL || names != NULL) { tznames = new TZNames(names); if (tznames == NULL) { if (locationNameOwned) { uprv_free(locationNameOwned); } } tznames->fLocationName = locationName; tznames->fLocationNameOwned = locationNameOwned; } return tznames; }
static ListFormatInternal* loadListFormatInternal( const Locale& locale, const char * style, UErrorCode& errorCode) { UResourceBundle* rb = ures_open(NULL, locale.getName(), &errorCode); if (U_FAILURE(errorCode)) { ures_close(rb); return NULL; } rb = ures_getByKeyWithFallback(rb, "listPattern", rb, &errorCode); rb = ures_getByKeyWithFallback(rb, style, rb, &errorCode); // TODO(Travis Keep): This is a hack until fallbacks can be added for // listPattern/duration and listPattern/duration-narrow in CLDR. if (errorCode == U_MISSING_RESOURCE_ERROR) { errorCode = U_ZERO_ERROR; rb = ures_getByKeyWithFallback(rb, "standard", rb, &errorCode); } if (U_FAILURE(errorCode)) { ures_close(rb); return NULL; } UnicodeString two, start, middle, end; getStringByKey(rb, "2", two, errorCode); getStringByKey(rb, "start", start, errorCode); getStringByKey(rb, "middle", middle, errorCode); getStringByKey(rb, "end", end, errorCode); ures_close(rb); if (U_FAILURE(errorCode)) { return NULL; } ListFormatInternal* result = new ListFormatInternal(two, start, middle, end); if (result == NULL) { errorCode = U_MEMORY_ALLOCATION_ERROR; return NULL; } return result; }
void RelativeDateFormat::loadDates(UErrorCode &status) { UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status); LocalUResourceBundlePointer dateTimePatterns( ures_getByKeyWithFallback(rb, "calendar/gregorian/DateTimePatterns", (UResourceBundle*)NULL, &status)); if(U_SUCCESS(status)) { int32_t patternsSize = ures_getSize(dateTimePatterns.getAlias()); if (patternsSize > kDateTime) { int32_t resStrLen = 0; int32_t glueIndex = kDateTime; if (patternsSize >= (kDateTimeOffset + kShort + 1)) { int32_t offsetIncrement = (fDateStyle & ~kRelative); // Remove relative bit. if (offsetIncrement >= (int32_t)kFull && offsetIncrement <= (int32_t)kShortRelative) { glueIndex = kDateTimeOffset + offsetIncrement; } } const UChar *resStr = ures_getStringByIndex(dateTimePatterns.getAlias(), glueIndex, &resStrLen, &status); if (U_SUCCESS(status) && resStrLen >= patItem1Len && u_strncmp(resStr,patItem1,patItem1Len)==0) { fCombinedHasDateAtStart = TRUE; } fCombinedFormat = new SimpleFormatter(UnicodeString(TRUE, resStr, resStrLen), 2, 2, status); } } // Data loading for relative names, e.g., "yesterday", "today", "tomorrow". fDatesLen = UDAT_DIRECTION_COUNT; // Maximum defined by data. fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen); RelDateFmtDataSink sink(fDates, fDatesLen); ures_getAllItemsWithFallback(rb, "fields/day/relative", sink, status); ures_close(rb); if(U_FAILURE(status)) { fDatesLen=0; return; } }
void TimeZoneNamesImpl::initialize(const Locale& locale, UErrorCode& status) { if (U_FAILURE(status)) { return; } // Load zoneStrings bundle UErrorCode tmpsts = U_ZERO_ERROR; // OK with fallback warning.. fZoneStrings = ures_open(U_ICUDATA_ZONE, locale.getName(), &tmpsts); fZoneStrings = ures_getByKeyWithFallback(fZoneStrings, gZoneStrings, fZoneStrings, &tmpsts); if (U_FAILURE(tmpsts)) { status = tmpsts; cleanup(); return; } // Initialize hashtables holding time zone/meta zone names fMZNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); fTZNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); if (U_FAILURE(status)) { cleanup(); return; } uhash_setValueDeleter(fMZNamesMap, deleteZNames); uhash_setValueDeleter(fTZNamesMap, deleteTZNames); // no key deleters for name maps // preload zone strings for the default zone TimeZone *tz = TimeZone::createDefault(); const UChar *tzID = ZoneMeta::getCanonicalCLDRID(*tz); if (tzID != NULL) { loadStrings(UnicodeString(tzID)); } delete tz; return; }
U_CAPI UMeasurementSystem U_EXPORT2 ulocdata_getMeasurementSystem(const char *localeID, UErrorCode *status){ UResourceBundle* bundle=NULL; UResourceBundle* measurement=NULL; UMeasurementSystem system = UMS_LIMIT; if(status == NULL || U_FAILURE(*status)){ return system; } bundle = measurementDataBundleForLocale(localeID, status); measurement = ures_getByKeyWithFallback(bundle, MEASUREMENT_SYSTEM, NULL, status); system = (UMeasurementSystem) ures_getInt(measurement, status); ures_close(bundle); ures_close(measurement); return system; }
U_NAMESPACE_BEGIN // ------------------------------------- BreakIterator* BreakIterator::buildInstance(const Locale& loc, const char *type, int32_t kind, UErrorCode &status) { char fnbuff[256]; char ext[4]={'\0'}; char actualLocale[ULOC_FULLNAME_CAPACITY]; int32_t size; const UChar* brkfname = NULL; UResourceBundle brkRulesStack; UResourceBundle brkNameStack; UResourceBundle *brkRules = &brkRulesStack; UResourceBundle *brkName = &brkNameStack; RuleBasedBreakIterator *result = NULL; if (U_FAILURE(status)) return NULL; ures_initStackObject(brkRules); ures_initStackObject(brkName); // Get the locale UResourceBundle *b = ures_open(U_ICUDATA_BRKITR, loc.getName(), &status); /* this is a hack for now. Should be fixed when the data is fetched from brk_index.txt */ if(status==U_USING_DEFAULT_WARNING){ status=U_ZERO_ERROR; ures_openFillIn(b, U_ICUDATA_BRKITR, "", &status); } // Get the "boundaries" array. if (U_SUCCESS(status)) { brkRules = ures_getByKeyWithFallback(b, "boundaries", brkRules, &status); // Get the string object naming the rules file brkName = ures_getByKeyWithFallback(brkRules, type, brkName, &status); // Get the actual string brkfname = ures_getString(brkName, &size, &status); U_ASSERT((size_t)size<sizeof(fnbuff)); if ((size_t)size>=sizeof(fnbuff)) { size=0; if (U_SUCCESS(status)) { status = U_BUFFER_OVERFLOW_ERROR; } } // Use the string if we found it if (U_SUCCESS(status) && brkfname) { uprv_strncpy(actualLocale, ures_getLocale(brkName, &status), sizeof(actualLocale)/sizeof(actualLocale[0])); UChar* extStart=u_strchr(brkfname, 0x002e); int len = 0; if(extStart!=NULL){ len = (int)(extStart-brkfname); u_UCharsToChars(extStart+1, ext, sizeof(ext)); // nul terminates the buff u_UCharsToChars(brkfname, fnbuff, len); } fnbuff[len]=0; // nul terminate } } ures_close(brkRules); ures_close(brkName); UDataMemory* file = udata_open(U_ICUDATA_BRKITR, ext, fnbuff, &status); if (U_FAILURE(status)) { ures_close(b); return NULL; } // Create a RuleBasedBreakIterator result = new RuleBasedBreakIterator(file, status); // If there is a result, set the valid locale and actual locale, and the kind if (U_SUCCESS(status) && result != NULL) { U_LOCALE_BASED(locBased, *(BreakIterator*)result); locBased.setLocaleIDs(ures_getLocaleByType(b, ULOC_VALID_LOCALE, &status), actualLocale); result->setBreakType(kind); } ures_close(b); if (U_FAILURE(status) && result != NULL) { // Sometimes redundant check, but simple delete result; return NULL; } if (result == NULL) { udata_close(file); if (U_SUCCESS(status)) { status = U_MEMORY_ALLOCATION_ERROR; } } return result; }
void CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) { if (U_FAILURE(status)) { return; } fPluralCountToCurrencyUnitPattern = initHash(status); if (U_FAILURE(status)) { return; } UErrorCode ec = U_ZERO_ERROR; UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec); UResourceBundle *numberPatterns = ures_getByKey(rb, gNumberPatternsTag, NULL, &ec); int32_t ptnLen; // TODO: 0 to be NumberFormat::fNumberStyle const UChar* numberStylePattern = ures_getStringByIndex(numberPatterns, 0, &ptnLen, &ec); int32_t numberStylePatternLen = ptnLen; const UChar* negNumberStylePattern = NULL; int32_t negNumberStylePatternLen = 0; // TODO: Java // parse to check whether there is ";" separator in the numberStylePattern UBool hasSeparator = false; if (U_SUCCESS(ec)) { for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) { if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) { hasSeparator = true; // split the number style pattern into positive and negative negNumberStylePattern = numberStylePattern + styleCharIndex + 1; negNumberStylePatternLen = ptnLen - styleCharIndex - 1; numberStylePatternLen = styleCharIndex; } } } ures_close(numberPatterns); if (U_FAILURE(ec)) { ures_close(rb); return; } UResourceBundle *currencyRes = ures_getByKeyWithFallback(rb, gCurrUnitPtnTag, NULL, &ec); #ifdef CURRENCY_PLURAL_INFO_DEBUG std::cout << "in set up\n"; #endif StringEnumeration* keywords = fPluralRules->getKeywords(ec); if (U_SUCCESS(ec)) { const char* pluralCount; while ((pluralCount = keywords->next(NULL, ec)) != NULL) { if ( U_SUCCESS(ec) ) { int32_t ptnLen; UErrorCode err = U_ZERO_ERROR; const UChar* patternChars = ures_getStringByKeyWithFallback( currencyRes, pluralCount, &ptnLen, &err); if (U_SUCCESS(err) && ptnLen > 0) { UnicodeString* pattern = new UnicodeString(patternChars, ptnLen); #ifdef CURRENCY_PLURAL_INFO_DEBUG char result_1[1000]; pattern->extract(0, pattern->length(), result_1, "UTF-8"); std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; #endif pattern->findAndReplace(gPart0, UnicodeString(numberStylePattern, numberStylePatternLen)); pattern->findAndReplace(gPart1, gTripleCurrencySign); if (hasSeparator) { UnicodeString negPattern(patternChars, ptnLen); negPattern.findAndReplace(gPart0, UnicodeString(negNumberStylePattern, negNumberStylePatternLen)); negPattern.findAndReplace(gPart1, gTripleCurrencySign); pattern->append(gNumberPatternSeparator); pattern->append(negPattern); } #ifdef CURRENCY_PLURAL_INFO_DEBUG pattern->extract(0, pattern->length(), result_1, "UTF-8"); std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; #endif fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount), pattern, status); } } } } delete keywords; ures_close(currencyRes); ures_close(rb); }
void LocaleDisplayNamesImpl::initialize(void) { LocaleDisplayNamesImpl *nonConstThis = (LocaleDisplayNamesImpl *)this; nonConstThis->locale = langData.getLocale() == Locale::getRoot() ? regionData.getLocale() : langData.getLocale(); UnicodeString sep; langData.getNoFallback("localeDisplayPattern", "separator", sep); if (sep.isBogus()) { sep = UnicodeString("{0}, {1}", -1, US_INV); } UErrorCode status = U_ZERO_ERROR; separatorFormat.applyPatternMinMaxArguments(sep, 2, 2, status); UnicodeString pattern; langData.getNoFallback("localeDisplayPattern", "pattern", pattern); if (pattern.isBogus()) { pattern = UnicodeString("{0} ({1})", -1, US_INV); } format.applyPatternMinMaxArguments(pattern, 2, 2, status); if (pattern.indexOf((UChar)0xFF08) >= 0) { formatOpenParen.setTo((UChar)0xFF08); // fullwidth ( formatReplaceOpenParen.setTo((UChar)0xFF3B); // fullwidth [ formatCloseParen.setTo((UChar)0xFF09); // fullwidth ) formatReplaceCloseParen.setTo((UChar)0xFF3D); // fullwidth ] } else { formatOpenParen.setTo((UChar)0x0028); // ( formatReplaceOpenParen.setTo((UChar)0x005B); // [ formatCloseParen.setTo((UChar)0x0029); // ) formatReplaceCloseParen.setTo((UChar)0x005D); // ] } UnicodeString ktPattern; langData.get("localeDisplayPattern", "keyTypePattern", ktPattern); if (ktPattern.isBogus()) { ktPattern = UnicodeString("{0}={1}", -1, US_INV); } keyTypeFormat.applyPatternMinMaxArguments(ktPattern, 2, 2, status); uprv_memset(fCapitalization, 0, sizeof(fCapitalization)); #if !UCONFIG_NO_BREAK_ITERATION // The following is basically copied from DateFormatSymbols::initializeData typedef struct { const char * usageName; LocaleDisplayNamesImpl::CapContextUsage usageEnum; } ContextUsageNameToEnum; const ContextUsageNameToEnum contextUsageTypeMap[] = { // Entries must be sorted by usageTypeName; entry with NULL name terminates list. { "key", kCapContextUsageKey }, { "keyValue", kCapContextUsageKeyValue }, { "languages", kCapContextUsageLanguage }, { "script", kCapContextUsageScript }, { "territory", kCapContextUsageTerritory }, { "variant", kCapContextUsageVariant }, { NULL, (CapContextUsage)0 }, }; // Only get the context data if we need it! This is a const object so we know now... // Also check whether we will need a break iterator (depends on the data) UBool needBrkIter = FALSE; if (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_STANDALONE) { int32_t len = 0; UResourceBundle *localeBundle = ures_open(NULL, locale.getName(), &status); if (U_SUCCESS(status)) { UResourceBundle *contextTransforms = ures_getByKeyWithFallback(localeBundle, "contextTransforms", NULL, &status); if (U_SUCCESS(status)) { UResourceBundle *contextTransformUsage; while ( (contextTransformUsage = ures_getNextResource(contextTransforms, NULL, &status)) != NULL ) { const int32_t * intVector = ures_getIntVector(contextTransformUsage, &len, &status); if (U_SUCCESS(status) && intVector != NULL && len >= 2) { const char* usageKey = ures_getKey(contextTransformUsage); if (usageKey != NULL) { const ContextUsageNameToEnum * typeMapPtr = contextUsageTypeMap; int32_t compResult = 0; // linear search; list is short and we cannot be sure that bsearch is available while ( typeMapPtr->usageName != NULL && (compResult = uprv_strcmp(usageKey, typeMapPtr->usageName)) > 0 ) { ++typeMapPtr; } if (typeMapPtr->usageName != NULL && compResult == 0) { int32_t titlecaseInt = (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU)? intVector[0]: intVector[1]; if (titlecaseInt != 0) { fCapitalization[typeMapPtr->usageEnum] = TRUE;; needBrkIter = TRUE; } } } } status = U_ZERO_ERROR; ures_close(contextTransformUsage); } ures_close(contextTransforms); } ures_close(localeBundle); } } // Get a sentence break iterator if we will need it if (needBrkIter || capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE) { status = U_ZERO_ERROR; capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status); if (U_FAILURE(status)) { delete capitalizationBrkIter; capitalizationBrkIter = NULL; } } #endif }
U_CAPI int32_t U_EXPORT2 uloc_getDisplayKeywordValue( const char* locale, const char* keyword, const char* displayLocale, UChar* dest, int32_t destCapacity, UErrorCode* status){ char keywordValue[ULOC_FULLNAME_CAPACITY*4]; int32_t capacity = ULOC_FULLNAME_CAPACITY*4; int32_t keywordValueLen =0; /* argument checking */ if(status==NULL || U_FAILURE(*status)) { return 0; } if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { *status=U_ILLEGAL_ARGUMENT_ERROR; return 0; } /* get the keyword value */ keywordValue[0]=0; keywordValueLen = uloc_getKeywordValue(locale, keyword, keywordValue, capacity, status); /* * if the keyword is equal to currency .. then to get the display name * we need to do the fallback ourselves */ if(uprv_stricmp(keyword, _kCurrency)==0){ int32_t dispNameLen = 0; const UChar *dispName = NULL; UResourceBundle *bundle = ures_open(U_ICUDATA_CURR, displayLocale, status); UResourceBundle *currencies = ures_getByKey(bundle, _kCurrencies, NULL, status); UResourceBundle *currency = ures_getByKeyWithFallback(currencies, keywordValue, NULL, status); dispName = ures_getStringByIndex(currency, UCURRENCY_DISPLAY_NAME_INDEX, &dispNameLen, status); /*close the bundles */ ures_close(currency); ures_close(currencies); ures_close(bundle); if(U_FAILURE(*status)){ if(*status == U_MISSING_RESOURCE_ERROR){ /* we just want to write the value over if nothing is available */ *status = U_USING_DEFAULT_WARNING; }else{ return 0; } } /* now copy the dispName over if not NULL */ if(dispName != NULL){ if(dispNameLen <= destCapacity){ uprv_memcpy(dest, dispName, dispNameLen * U_SIZEOF_UCHAR); return u_terminateUChars(dest, destCapacity, dispNameLen, status); }else{ *status = U_BUFFER_OVERFLOW_ERROR; return dispNameLen; } }else{ /* we have not found the display name for the value .. just copy over */ if(keywordValueLen <= destCapacity){ u_charsToUChars(keywordValue, dest, keywordValueLen); return u_terminateUChars(dest, destCapacity, keywordValueLen, status); }else{ *status = U_BUFFER_OVERFLOW_ERROR; return keywordValueLen; } } }else{ return _getStringOrCopyKey(U_ICUDATA_LANG, displayLocale, _kTypes, keyword, keywordValue, keywordValue, dest, destCapacity, status); } }
/* Instead of having a separate pass for 'special' patterns, reintegrate the two * so we don't get bitten by preflight bugs again. We can be reasonably efficient * without two separate code paths, this code isn't that performance-critical. * * This code is general enough to deal with patterns that have a prefix or swap the * language and remainder components, since we gave developers enough rope to do such * things if they futz with the pattern data. But since we don't give them a way to * specify a pattern for arbitrary combinations of components, there's not much use in * that. I don't think our data includes such patterns, the only variable I know if is * whether there is a space before the open paren, or not. Oh, and zh uses different * chars than the standard open/close paren (which ja and ko use, btw). */ U_CAPI int32_t U_EXPORT2 uloc_getDisplayName(const char *locale, const char *displayLocale, UChar *dest, int32_t destCapacity, UErrorCode *pErrorCode) { static const UChar defaultSeparator[9] = { 0x007b, 0x0030, 0x007d, 0x002c, 0x0020, 0x007b, 0x0031, 0x007d, 0x0000 }; /* "{0}, {1}" */ static const UChar sub0[4] = { 0x007b, 0x0030, 0x007d , 0x0000 } ; /* {0} */ static const UChar sub1[4] = { 0x007b, 0x0031, 0x007d , 0x0000 } ; /* {1} */ static const int32_t subLen = 3; static const UChar defaultPattern[10] = { 0x007b, 0x0030, 0x007d, 0x0020, 0x0028, 0x007b, 0x0031, 0x007d, 0x0029, 0x0000 }; /* {0} ({1}) */ static const int32_t defaultPatLen = 9; static const int32_t defaultSub0Pos = 0; static const int32_t defaultSub1Pos = 5; int32_t length; /* of formatted result */ const UChar *separator; int32_t sepLen = 0; const UChar *pattern; int32_t patLen = 0; int32_t sub0Pos, sub1Pos; UChar formatOpenParen = 0x0028; // ( UChar formatReplaceOpenParen = 0x005B; // [ UChar formatCloseParen = 0x0029; // ) UChar formatReplaceCloseParen = 0x005D; // ] UBool haveLang = TRUE; /* assume true, set false if we find we don't have a lang component in the locale */ UBool haveRest = TRUE; /* assume true, set false if we find we don't have any other component in the locale */ UBool retry = FALSE; /* set true if we need to retry, see below */ int32_t langi = 0; /* index of the language substitution (0 or 1), virtually always 0 */ if(pErrorCode==NULL || U_FAILURE(*pErrorCode)) { return 0; } if(destCapacity<0 || (destCapacity>0 && dest==NULL)) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } { UErrorCode status = U_ZERO_ERROR; UResourceBundle* locbundle=ures_open(U_ICUDATA_LANG, displayLocale, &status); UResourceBundle* dspbundle=ures_getByKeyWithFallback(locbundle, _kLocaleDisplayPattern, NULL, &status); separator=ures_getStringByKeyWithFallback(dspbundle, _kSeparator, &sepLen, &status); pattern=ures_getStringByKeyWithFallback(dspbundle, _kPattern, &patLen, &status); ures_close(dspbundle); ures_close(locbundle); } /* If we couldn't find any data, then use the defaults */ if(sepLen == 0) { separator = defaultSeparator; } /* #10244: Even though separator is now a pattern, it is awkward to handle it as such * here since we are trying to build the display string in place in the dest buffer, * and to handle it as a pattern would entail having separate storage for the * substrings that need to be combined (the first of which may be the result of * previous such combinations). So for now we continue to treat the portion between * {0} and {1} as a string to be appended when joining substrings, ignoring anything * that is before {0} or after {1} (no existing separator pattern has any such thing). * This is similar to how pattern is handled below. */ { UChar *p0=u_strstr(separator, sub0); UChar *p1=u_strstr(separator, sub1); if (p0==NULL || p1==NULL || p1<p0) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } separator = (const UChar *)p0 + subLen; sepLen = p1 - separator; } if(patLen==0 || (patLen==defaultPatLen && !u_strncmp(pattern, defaultPattern, patLen))) { pattern=defaultPattern; patLen=defaultPatLen; sub0Pos=defaultSub0Pos; sub1Pos=defaultSub1Pos; // use default formatOpenParen etc. set above } else { /* non-default pattern */ UChar *p0=u_strstr(pattern, sub0); UChar *p1=u_strstr(pattern, sub1); if (p0==NULL || p1==NULL) { *pErrorCode=U_ILLEGAL_ARGUMENT_ERROR; return 0; } sub0Pos=p0-pattern; sub1Pos=p1-pattern; if (sub1Pos < sub0Pos) { /* a very odd pattern */ int32_t t=sub0Pos; sub0Pos=sub1Pos; sub1Pos=t; langi=1; } if (u_strchr(pattern, 0xFF08) != NULL) { formatOpenParen = 0xFF08; // fullwidth ( formatReplaceOpenParen = 0xFF3B; // fullwidth [ formatCloseParen = 0xFF09; // fullwidth ) formatReplaceCloseParen = 0xFF3D; // fullwidth ] } } /* We loop here because there is one case in which after the first pass we could need to * reextract the data. If there's initial padding before the first element, we put in * the padding and then write that element. If it turns out there's no second element, * we didn't need the padding. If we do need the data (no preflight), and the first element * would have fit but for the padding, we need to reextract. In this case (only) we * adjust the parameters so padding is not added, and repeat. */ do { UChar* p=dest; int32_t patPos=0; /* position in the pattern, used for non-substitution portions */ int32_t langLen=0; /* length of language substitution */ int32_t langPos=0; /* position in output of language substitution */ int32_t restLen=0; /* length of 'everything else' substitution */ int32_t restPos=0; /* position in output of 'everything else' substitution */ UEnumeration* kenum = NULL; /* keyword enumeration */ /* prefix of pattern, extremely likely to be empty */ if(sub0Pos) { if(destCapacity >= sub0Pos) { while (patPos < sub0Pos) { *p++ = pattern[patPos++]; } } else { patPos=sub0Pos; } length=sub0Pos; } else { length=0; } for(int32_t subi=0,resti=0;subi<2;) { /* iterate through patterns 0 and 1*/ UBool subdone = FALSE; /* set true when ready to move to next substitution */ /* prep p and cap for calls to get display components, pin cap to 0 since they complain if cap is negative */ int32_t cap=destCapacity-length; if (cap <= 0) { cap=0; } else { p=dest+length; } if (subi == langi) { /* {0}*/ if(haveLang) { langPos=length; langLen=uloc_getDisplayLanguage(locale, displayLocale, p, cap, pErrorCode); length+=langLen; haveLang=langLen>0; } subdone=TRUE; } else { /* {1} */ if(!haveRest) { subdone=TRUE; } else { int32_t len; /* length of component (plus other stuff) we just fetched */ switch(resti++) { case 0: restPos=length; len=uloc_getDisplayScriptInContext(locale, displayLocale, p, cap, pErrorCode); break; case 1: len=uloc_getDisplayCountry(locale, displayLocale, p, cap, pErrorCode); break; case 2: len=uloc_getDisplayVariant(locale, displayLocale, p, cap, pErrorCode); break; case 3: kenum = uloc_openKeywords(locale, pErrorCode); /* fall through */ default: { const char* kw=uenum_next(kenum, &len, pErrorCode); if (kw == NULL) { uenum_close(kenum); len=0; /* mark that we didn't add a component */ subdone=TRUE; } else { /* incorporating this behavior into the loop made it even more complex, so just special case it here */ len = uloc_getDisplayKeyword(kw, displayLocale, p, cap, pErrorCode); if(len) { if(len < cap) { p[len]=0x3d; /* '=', assume we'll need it */ } len+=1; /* adjust for call to get keyword */ cap-=len; if(cap <= 0) { cap=0; } else { p+=len; } } /* reset for call below */ if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { *pErrorCode=U_ZERO_ERROR; } int32_t vlen = uloc_getDisplayKeywordValue(locale, kw, displayLocale, p, cap, pErrorCode); if(len) { if(vlen==0) { --len; /* remove unneeded '=' */ } /* restore cap and p to what they were at start */ cap=destCapacity-length; if(cap <= 0) { cap=0; } else { p=dest+length; } } len+=vlen; /* total we added for key + '=' + value */ } } break; } /* end switch */ if (len>0) { /* we addeed a component, so add separator and write it if there's room. */ if(len+sepLen<=cap) { const UChar * plimit = p + len; for (; p < plimit; p++) { if (*p == formatOpenParen) { *p = formatReplaceOpenParen; } else if (*p == formatCloseParen) { *p = formatReplaceCloseParen; } } for(int32_t i=0;i<sepLen;++i) { *p++=separator[i]; } } length+=len+sepLen; } else if(subdone) { /* remove separator if we added it */ if (length!=restPos) { length-=sepLen; } restLen=length-restPos; haveRest=restLen>0; } } } if(*pErrorCode == U_BUFFER_OVERFLOW_ERROR) { *pErrorCode=U_ZERO_ERROR; } if(subdone) { if(haveLang && haveRest) { /* append internal portion of pattern, the first time, or last portion of pattern the second time */ int32_t padLen; patPos+=subLen; padLen=(subi==0 ? sub1Pos : patLen)-patPos; if(length+padLen < destCapacity) { p=dest+length; for(int32_t i=0;i<padLen;++i) { *p++=pattern[patPos++]; } } else { patPos+=padLen; } length+=padLen; } else if(subi==0) { /* don't have first component, reset for second component */ sub0Pos=0; length=0; } else if(length>0) { /* true length is the length of just the component we got. */ length=haveLang?langLen:restLen; if(dest && sub0Pos!=0) { if (sub0Pos+length<=destCapacity) { /* first component not at start of result, but we have full component in buffer. */ u_memmove(dest, dest+(haveLang?langPos:restPos), length); } else { /* would have fit, but didn't because of pattern prefix. */ sub0Pos=0; /* stops initial padding (and a second retry, so we won't end up here again) */ retry=TRUE; } } } ++subi; /* move on to next substitution */ } } } while(retry); return u_terminateUChars(dest, destCapacity, length, pErrorCode); }
void DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData) { static const char *gNumberElementKeys[kFormatSymbolCount] = { "decimal", "group", "list", "percentSign", NULL, /* Native zero digit is deprecated from CLDR - get it from the numbering system */ NULL, /* Pattern digit character is deprecated from CLDR - use # by default always */ "minusSign", "plusSign", NULL, /* currency symbol - We don't really try to load this directly from CLDR until we know the currency */ NULL, /* intl currency symbol - We don't really try to load this directly from CLDR until we know the currency */ "currencyDecimal", "exponential", "perMille", NULL, /* Escape padding character - not in CLDR */ "infinity", "nan", NULL, /* Significant digit symbol - not in CLDR */ "currencyGroup", NULL, /* one digit - get it from the numbering system */ NULL, /* two digit - get it from the numbering system */ NULL, /* three digit - get it from the numbering system */ NULL, /* four digit - get it from the numbering system */ NULL, /* five digit - get it from the numbering system */ NULL, /* six digit - get it from the numbering system */ NULL, /* seven digit - get it from the numbering system */ NULL, /* eight digit - get it from the numbering system */ NULL, /* nine digit - get it from the numbering system */ "superscriptingExponent", /* Multiplication (x) symbol for exponents */ }; static const char *gLatn = "latn"; static const char *gSymbols = "symbols"; const char *nsName; const UChar *sym = NULL; int32_t len = 0; *validLocale = *actualLocale = 0; currPattern = NULL; if (U_FAILURE(status)) return; const char* locStr = loc.getName(); LocalUResourceBundlePointer resource(ures_open(NULL, locStr, &status)); LocalUResourceBundlePointer numberElementsRes( ures_getByKeyWithFallback(resource.getAlias(), gNumberElements, NULL, &status)); if (U_FAILURE(status)) { if ( useLastResortData ) { status = U_USING_DEFAULT_WARNING; initialize(); } return; } // First initialize all the symbols to the fallbacks for anything we can't find initialize(); // // Next get the numbering system for this locale and set zero digit // and the digit string based on the numbering system for the locale // LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(loc, status)); if (U_SUCCESS(status) && ns->getRadix() == 10 && !ns->isAlgorithmic()) { nsName = ns->getName(); UnicodeString digitString(ns->getDescription()); int32_t digitIndex = 0; UChar32 digit = digitString.char32At(0); fSymbols[kZeroDigitSymbol].setTo(digit); for (int32_t i = kOneDigitSymbol; i <= kNineDigitSymbol; ++i) { digitIndex += U16_LENGTH(digit); digit = digitString.char32At(digitIndex); fSymbols[i].setTo(digit); } } else { nsName = gLatn; } UBool isLatn = !uprv_strcmp(nsName,gLatn); UErrorCode nlStatus = U_ZERO_ERROR; LocalUResourceBundlePointer nonLatnSymbols; if ( !isLatn ) { nonLatnSymbols.adoptInstead( ures_getByKeyWithFallback(numberElementsRes.getAlias(), nsName, NULL, &nlStatus)); ures_getByKeyWithFallback(nonLatnSymbols.getAlias(), gSymbols, nonLatnSymbols.getAlias(), &nlStatus); } LocalUResourceBundlePointer latnSymbols( ures_getByKeyWithFallback(numberElementsRes.getAlias(), gLatn, NULL, &status)); ures_getByKeyWithFallback(latnSymbols.getAlias(), gSymbols, latnSymbols.getAlias(), &status); UBool kMonetaryDecimalSet = FALSE; UBool kMonetaryGroupingSet = FALSE; for(int32_t i = 0; i<kFormatSymbolCount; i++) { if ( gNumberElementKeys[i] != NULL ) { UErrorCode localStatus = U_ZERO_ERROR; if ( !isLatn ) { sym = ures_getStringByKeyWithFallback(nonLatnSymbols.getAlias(), gNumberElementKeys[i], &len, &localStatus); // If we can't find the symbol in the numbering system specific resources, // use the "latn" numbering system as the fallback. if ( U_FAILURE(localStatus) ) { localStatus = U_ZERO_ERROR; sym = ures_getStringByKeyWithFallback(latnSymbols.getAlias(), gNumberElementKeys[i], &len, &localStatus); } } else { sym = ures_getStringByKeyWithFallback(latnSymbols.getAlias(), gNumberElementKeys[i], &len, &localStatus); } if ( U_SUCCESS(localStatus) ) { setSymbol((ENumberFormatSymbol)i, UnicodeString(TRUE, sym, len)); if ( i == kMonetarySeparatorSymbol ) { kMonetaryDecimalSet = TRUE; } else if ( i == kMonetaryGroupingSeparatorSymbol ) { kMonetaryGroupingSet = TRUE; } } } } // If monetary decimal or grouping were not explicitly set, then set them to be the // same as their non-monetary counterparts. if ( !kMonetaryDecimalSet ) { setSymbol(kMonetarySeparatorSymbol,fSymbols[kDecimalSeparatorSymbol]); } if ( !kMonetaryGroupingSet ) { setSymbol(kMonetaryGroupingSeparatorSymbol,fSymbols[kGroupingSeparatorSymbol]); } // Obtain currency data from the currency API. This is strictly // for backward compatibility; we don't use DecimalFormatSymbols // for currency data anymore. UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out UChar curriso[4]; UnicodeString tempStr; ucurr_forLocale(locStr, curriso, 4, &internalStatus); uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); if (U_SUCCESS(internalStatus)) { fSymbols[kIntlCurrencySymbol].setTo(curriso, -1); fSymbols[kCurrencySymbol] = tempStr; } /* else use the default values. */ U_LOCALE_BASED(locBased, *this); locBased.setLocaleIDs(ures_getLocaleByType(numberElementsRes.getAlias(), ULOC_VALID_LOCALE, &status), ures_getLocaleByType(numberElementsRes.getAlias(), ULOC_ACTUAL_LOCALE, &status)); //load the currency data UChar ucc[4]={0}; //Currency Codes are always 3 chars long int32_t uccLen = 4; const char* locName = loc.getName(); UErrorCode localStatus = U_ZERO_ERROR; uccLen = ucurr_forLocale(locName, ucc, uccLen, &localStatus); if(U_SUCCESS(localStatus) && uccLen > 0) { char cc[4]={0}; u_UCharsToChars(ucc, cc, uccLen); /* An explicit currency was requested */ LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); LocalUResourceBundlePointer currency( ures_getByKeyWithFallback(currencyResource.getAlias(), "Currencies", NULL, &localStatus)); ures_getByKeyWithFallback(currency.getAlias(), cc, currency.getAlias(), &localStatus); if(U_SUCCESS(localStatus) && ures_getSize(currency.getAlias())>2) { // the length is 3 if more data is present ures_getByIndex(currency.getAlias(), 2, currency.getAlias(), &localStatus); int32_t currPatternLen = 0; currPattern = ures_getStringByIndex(currency.getAlias(), (int32_t)0, &currPatternLen, &localStatus); UnicodeString decimalSep = ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)1, &localStatus); UnicodeString groupingSep = ures_getUnicodeStringByIndex(currency.getAlias(), (int32_t)2, &localStatus); if(U_SUCCESS(localStatus)){ fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; fSymbols[kMonetarySeparatorSymbol] = decimalSep; //pattern.setTo(TRUE, currPattern, currPatternLen); status = localStatus; } } /* else An explicit currency was requested and is unknown or locale data is malformed. */ /* ucurr_* API will get the correct value later on. */ } // else ignore the error if no currency // Currency Spacing. localStatus = U_ZERO_ERROR; LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &localStatus)); LocalUResourceBundlePointer currencySpcRes( ures_getByKeyWithFallback(currencyResource.getAlias(), gCurrencySpacingTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { const char* keywords[UNUM_CURRENCY_SPACING_COUNT] = { gCurrencyMatchTag, gCurrencySudMatchTag, gCurrencyInsertBtnTag }; localStatus = U_ZERO_ERROR; LocalUResourceBundlePointer dataRes( ures_getByKeyWithFallback(currencySpcRes.getAlias(), gBeforeCurrencyTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { localStatus = U_ZERO_ERROR; for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) { currencySpcBeforeSym[i] = ures_getUnicodeStringByKey(dataRes.getAlias(), keywords[i], &localStatus); } } dataRes.adoptInstead( ures_getByKeyWithFallback(currencySpcRes.getAlias(), gAfterCurrencyTag, NULL, &localStatus)); if (localStatus == U_USING_FALLBACK_WARNING || U_SUCCESS(localStatus)) { localStatus = U_ZERO_ERROR; for (int32_t i = 0; i < UNUM_CURRENCY_SPACING_COUNT; i++) { currencySpcAfterSym[i] = ures_getUnicodeStringByKey(dataRes.getAlias(), keywords[i], &localStatus); } } } }
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; }
void RelativeDateFormat::loadDates(UErrorCode &status) { CalendarData calData(fLocale, "gregorian", status); UErrorCode tempStatus = status; UResourceBundle *dateTimePatterns = calData.getByKey(DT_DateTimePatternsTag, tempStatus); if(U_SUCCESS(tempStatus)) { int32_t patternsSize = ures_getSize(dateTimePatterns); if (patternsSize > kDateTime) { int32_t resStrLen = 0; int32_t glueIndex = kDateTime; if (patternsSize >= (DateFormat::kDateTimeOffset + DateFormat::kShort + 1)) { // Get proper date time format switch (fDateStyle) { case kFullRelative: case kFull: glueIndex = kDateTimeOffset + kFull; break; case kLongRelative: case kLong: glueIndex = kDateTimeOffset + kLong; break; case kMediumRelative: case kMedium: glueIndex = kDateTimeOffset + kMedium; break; case kShortRelative: case kShort: glueIndex = kDateTimeOffset + kShort; break; default: break; } } const UChar *resStr = ures_getStringByIndex(dateTimePatterns, glueIndex, &resStrLen, &tempStatus); if (U_SUCCESS(tempStatus) && resStrLen >= patItem1Len && u_strncmp(resStr,patItem1,patItem1Len)==0) { fCombinedHasDateAtStart = TRUE; } fCombinedFormat = new SimpleFormatter(UnicodeString(TRUE, resStr, resStrLen), 2, 2, tempStatus); } } UResourceBundle *rb = ures_open(NULL, fLocale.getBaseName(), &status); rb = ures_getByKeyWithFallback(rb, "fields", rb, &status); rb = ures_getByKeyWithFallback(rb, "day", rb, &status); rb = ures_getByKeyWithFallback(rb, "relative", rb, &status); // set up min/max fDayMin=-1; fDayMax=1; if(U_FAILURE(status)) { fDatesLen=0; ures_close(rb); return; } fDatesLen = ures_getSize(rb); fDates = (URelativeString*) uprv_malloc(sizeof(fDates[0])*fDatesLen); // Load in each item into the array... int n = 0; UResourceBundle *subString = NULL; while(ures_hasNext(rb) && U_SUCCESS(status)) { // iterate over items subString = ures_getNextResource(rb, subString, &status); if(U_FAILURE(status) || (subString==NULL)) break; // key = offset # const char *key = ures_getKey(subString); // load the string and length int32_t aLen; const UChar* aString = ures_getString(subString, &aLen, &status); if(U_FAILURE(status) || aString == NULL) break; // calculate the offset int32_t offset = atoi(key); // set min/max if(offset < fDayMin) { fDayMin = offset; } if(offset > fDayMax) { fDayMax = offset; } // copy the string pointer fDates[n].offset = offset; fDates[n].string = aString; fDates[n].len = aLen; n++; } ures_close(subString); ures_close(rb); // the fDates[] array could be sorted here, for direct access. }
void DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData) { *validLocale = *actualLocale = 0; currPattern = NULL; if (U_FAILURE(status)) return; const char* locStr = loc.getName(); UResourceBundle *resource = ures_open((char *)0, locStr, &status); UResourceBundle *numberElementsRes = ures_getByKey(resource, gNumberElements, NULL, &status); if (U_FAILURE(status)) { // Initializes with last resort data if necessary. if (useLastResortData) { status = U_USING_FALLBACK_WARNING; initialize(); } } else { // Gets the number element array. int32_t numberElementsLength = ures_getSize(numberElementsRes); if (numberElementsLength > (int32_t)kFormatSymbolCount) { /* Warning: Invalid format. Array too large. */ numberElementsLength = (int32_t)kFormatSymbolCount; } // If the array size is too small, something is wrong with the resource // bundle, returns the failure error code. if (numberElementsLength != 12 || U_FAILURE(status)) { status = U_INVALID_FORMAT_ERROR; } else { const UChar *numberElements[kFormatSymbolCount]; int32_t numberElementsStrLen[kFormatSymbolCount]; int32_t i = 0; for(i = 0; i<numberElementsLength; i++) { numberElements[i] = ures_getStringByIndex(numberElementsRes, i, &numberElementsStrLen[i], &status); } if (U_SUCCESS(status)) { initialize(numberElements, numberElementsStrLen, numberElementsLength); // Obtain currency data from the currency API. This is strictly // for backward compatibility; we don't use DecimalFormatSymbols // for currency data anymore. UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out UChar curriso[4]; UnicodeString tempStr; ucurr_forLocale(locStr, curriso, 4, &internalStatus); // Reuse numberElements[0] as a temporary buffer uprv_getStaticCurrencyName(curriso, locStr, tempStr, internalStatus); if (U_SUCCESS(internalStatus)) { fSymbols[kIntlCurrencySymbol] = curriso; fSymbols[kCurrencySymbol] = tempStr; } /* else use the default values. */ } U_LOCALE_BASED(locBased, *this); locBased.setLocaleIDs(ures_getLocaleByType(numberElementsRes, ULOC_VALID_LOCALE, &status), ures_getLocaleByType(numberElementsRes, ULOC_ACTUAL_LOCALE, &status)); } //load the currency data UChar ucc[4]= {0}; //Currency Codes are always 3 chars long int32_t uccLen = 4; const char* locName = loc.getName(); uccLen = ucurr_forLocale(locName, ucc, uccLen, &status); if(U_SUCCESS(status) && uccLen > 0) { char cc[4]= {0}; u_UCharsToChars(ucc, cc, uccLen); /* An explicit currency was requested */ UErrorCode localStatus = U_ZERO_ERROR; UResourceBundle *currency = ures_getByKeyWithFallback(resource, "Currencies", NULL, &localStatus); currency = ures_getByKeyWithFallback(currency, cc, currency, &localStatus); if(U_SUCCESS(localStatus) && ures_getSize(currency)>2) { // the length is 3 if more data is present currency = ures_getByIndex(currency, 2, currency, &localStatus); int32_t currPatternLen = 0; currPattern = ures_getStringByIndex(currency, (int32_t)0, &currPatternLen, &localStatus); UnicodeString decimalSep = ures_getStringByIndex(currency, (int32_t)1, NULL, &localStatus); UnicodeString groupingSep = ures_getStringByIndex(currency, (int32_t)2, NULL, &localStatus); if(U_SUCCESS(localStatus)) { fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep; fSymbols[kMonetarySeparatorSymbol] = decimalSep; //pattern.setTo(TRUE, currPattern, currPatternLen); status = localStatus; } } ures_close(currency); /* else An explicit currency was requested and is unknown or locale data is malformed. */ /* ucurr_* API will get the correct value later on. */ } else { // ignore the error if no currency status = U_ZERO_ERROR; } } ures_close(resource); ures_close(numberElementsRes); }
U_CFUNC UCollator* ucol_open_internal(const char *loc, UErrorCode *status) { const UCollator* UCA = ucol_initUCA(status); /* New version */ if(U_FAILURE(*status)) return 0; UCollator *result = NULL; UResourceBundle *b = ures_open(U_ICUDATA_COLL, loc, status); /* we try to find stuff from keyword */ UResourceBundle *collations = ures_getByKey(b, "collations", NULL, status); UResourceBundle *collElem = NULL; char keyBuffer[256]; // if there is a keyword, we pick it up and try to get elements if(!uloc_getKeywordValue(loc, "collation", keyBuffer, 256, status)) { // no keyword. we try to find the default setting, which will give us the keyword value UErrorCode intStatus = U_ZERO_ERROR; // finding default value does not affect collation fallback status UResourceBundle *defaultColl = ures_getByKeyWithFallback(collations, "default", NULL, &intStatus); if(U_SUCCESS(intStatus)) { int32_t defaultKeyLen = 0; const UChar *defaultKey = ures_getString(defaultColl, &defaultKeyLen, &intStatus); u_UCharsToChars(defaultKey, keyBuffer, defaultKeyLen); keyBuffer[defaultKeyLen] = 0; } else { *status = U_INTERNAL_PROGRAM_ERROR; return NULL; } ures_close(defaultColl); } collElem = ures_getByKeyWithFallback(collations, keyBuffer, collElem, status); UResourceBundle *binary = NULL; if(*status == U_MISSING_RESOURCE_ERROR) { /* We didn't find the tailoring data, we fallback to the UCA */ *status = U_USING_DEFAULT_WARNING; result = ucol_initCollator(UCA->image, result, UCA, status); // if we use UCA, real locale is root result->rb = ures_open(U_ICUDATA_COLL, "", status); result->elements = ures_open(U_ICUDATA_COLL, "", status); if(U_FAILURE(*status)) { goto clean; } ures_close(b); result->hasRealData = FALSE; } else if(U_SUCCESS(*status)) { int32_t len = 0; UErrorCode binaryStatus = U_ZERO_ERROR; binary = ures_getByKey(collElem, "%%CollationBin", NULL, &binaryStatus); if(binaryStatus == U_MISSING_RESOURCE_ERROR) { /* we didn't find the binary image, we should use the rules */ binary = NULL; result = tryOpeningFromRules(collElem, status); if(U_FAILURE(*status)) { goto clean; } } else if(U_SUCCESS(*status)) { /* otherwise, we'll pick a collation data that exists */ const uint8_t *inData = ures_getBinary(binary, &len, status); UCATableHeader *colData = (UCATableHeader *)inData; if(uprv_memcmp(colData->UCAVersion, UCA->image->UCAVersion, sizeof(UVersionInfo)) != 0 || uprv_memcmp(colData->UCDVersion, UCA->image->UCDVersion, sizeof(UVersionInfo)) != 0 || colData->version[0] != UCOL_BUILDER_VERSION) { *status = U_DIFFERENT_UCA_VERSION; result = tryOpeningFromRules(collElem, status); } else { if(U_FAILURE(*status)){ goto clean; } if((uint32_t)len > (paddedsize(sizeof(UCATableHeader)) + paddedsize(sizeof(UColOptionSet)))) { result = ucol_initCollator((const UCATableHeader *)inData, result, UCA, status); if(U_FAILURE(*status)){ goto clean; } result->hasRealData = TRUE; } else { result = ucol_initCollator(UCA->image, result, UCA, status); ucol_setOptionsFromHeader(result, (UColOptionSet *)(inData+((const UCATableHeader *)inData)->options), status); if(U_FAILURE(*status)){ goto clean; } result->hasRealData = FALSE; } result->freeImageOnClose = FALSE; } } result->rb = b; result->elements = collElem; len = 0; binaryStatus = U_ZERO_ERROR; result->rules = ures_getStringByKey(result->elements, "Sequence", &len, &binaryStatus); result->rulesLength = len; result->freeRulesOnClose = FALSE; } else { /* There is another error, and we're just gonna clean up */ goto clean; } result->validLocale = NULL; // default is to use rb info if(loc == NULL) { loc = ures_getLocale(result->rb, status); } result->requestedLocale = (char *)uprv_malloc((uprv_strlen(loc)+1)*sizeof(char)); /* test for NULL */ if (result->requestedLocale == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; goto clean; } uprv_strcpy(result->requestedLocale, loc); ures_close(binary); ures_close(collations); //??? we have to decide on that. Probably affects something :) result->resCleaner = ucol_prv_closeResources; return result; clean: ures_close(b); ures_close(collElem); ures_close(collations); ures_close(binary); return NULL; }
void CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) { if (U_FAILURE(status)) { return; } if (fPluralCountToCurrencyUnitPattern) { deleteHash(fPluralCountToCurrencyUnitPattern); } fPluralCountToCurrencyUnitPattern = initHash(status); if (U_FAILURE(status)) { return; } NumberingSystem *ns = NumberingSystem::createInstance(loc,status); UErrorCode ec = U_ZERO_ERROR; UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec); UResourceBundle *numElements = ures_getByKeyWithFallback(rb, gNumberElementsTag, NULL, &ec); rb = ures_getByKeyWithFallback(numElements, ns->getName(), rb, &ec); rb = ures_getByKeyWithFallback(rb, gPatternsTag, rb, &ec); int32_t ptnLen; const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec); // Fall back to "latn" if num sys specific pattern isn't there. if ( ec == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),gLatnTag)) { ec = U_ZERO_ERROR; rb = ures_getByKeyWithFallback(numElements, gLatnTag, rb, &ec); rb = ures_getByKeyWithFallback(rb, gPatternsTag, rb, &ec); numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec); } int32_t numberStylePatternLen = ptnLen; const UChar* negNumberStylePattern = NULL; int32_t negNumberStylePatternLen = 0; // TODO: Java // parse to check whether there is ";" separator in the numberStylePattern UBool hasSeparator = false; if (U_SUCCESS(ec)) { for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) { if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) { hasSeparator = true; // split the number style pattern into positive and negative negNumberStylePattern = numberStylePattern + styleCharIndex + 1; negNumberStylePatternLen = ptnLen - styleCharIndex - 1; numberStylePatternLen = styleCharIndex; } } } ures_close(numElements); ures_close(rb); delete ns; if (U_FAILURE(ec)) { return; } UResourceBundle *currRb = ures_open(U_ICUDATA_CURR, loc.getName(), &ec); UResourceBundle *currencyRes = ures_getByKeyWithFallback(currRb, gCurrUnitPtnTag, NULL, &ec); #ifdef CURRENCY_PLURAL_INFO_DEBUG std::cout << "in set up\n"; #endif StringEnumeration* keywords = fPluralRules->getKeywords(ec); if (U_SUCCESS(ec)) { const char* pluralCount; while ((pluralCount = keywords->next(NULL, ec)) != NULL) { if ( U_SUCCESS(ec) ) { int32_t ptnLen; UErrorCode err = U_ZERO_ERROR; const UChar* patternChars = ures_getStringByKeyWithFallback( currencyRes, pluralCount, &ptnLen, &err); if (U_SUCCESS(err) && ptnLen > 0) { UnicodeString* pattern = new UnicodeString(patternChars, ptnLen); #ifdef CURRENCY_PLURAL_INFO_DEBUG char result_1[1000]; pattern->extract(0, pattern->length(), result_1, "UTF-8"); std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; #endif pattern->findAndReplace(UnicodeString(TRUE, gPart0, 3), UnicodeString(numberStylePattern, numberStylePatternLen)); pattern->findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); if (hasSeparator) { UnicodeString negPattern(patternChars, ptnLen); negPattern.findAndReplace(UnicodeString(TRUE, gPart0, 3), UnicodeString(negNumberStylePattern, negNumberStylePatternLen)); negPattern.findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); pattern->append(gNumberPatternSeparator); pattern->append(negPattern); } #ifdef CURRENCY_PLURAL_INFO_DEBUG pattern->extract(0, pattern->length(), result_1, "UTF-8"); std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; #endif fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount, -1, US_INV), pattern, status); } } } } delete keywords; ures_close(currencyRes); ures_close(currRb); }
UResourceBundle* CalendarData::getByKey2(const char *key, const char *subKey, UErrorCode& status) { if(U_FAILURE(status)) { return NULL; } if(fBundle) { #if defined (U_DEBUG_CALDATA) fprintf(stderr, "%p: //\n"); #endif fFillin = ures_getByKeyWithFallback(fBundle, key, fFillin, &status); fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status); fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status); #if defined (U_DEBUG_CALDATA) fprintf(stderr, "%p: get %s/format/%s -> %s - from MAIN %s\n", this, key, subKey, u_errorName(status), ures_getLocale(fFillin, &status)); #endif } if(fFallback && (status == U_MISSING_RESOURCE_ERROR)) { status = U_ZERO_ERROR; // retry with fallback (gregorian) fFillin = ures_getByKeyWithFallback(fFallback, key, fFillin, &status); fOtherFillin = ures_getByKeyWithFallback(fFillin, U_FORMAT_KEY, fOtherFillin, &status); fFillin = ures_getByKeyWithFallback(fOtherFillin, subKey, fFillin, &status); #if defined (U_DEBUG_CALDATA) fprintf(stderr, "%p: get %s/format/%s -> %s - from FALLBACK %s\n",this, key, subKey, u_errorName(status), ures_getLocale(fFillin,&status)); #endif } //// handling of 'default' keyword on failure: Commented out for 3.0. // if((status == U_MISSING_RESOURCE_ERROR) && // uprv_strcmp(subKey,U_DEFAULT_KEY)) { // avoid recursion // #if defined (U_DEBUG_CALDATA) // fprintf(stderr, "%p: - attempting fallback -\n", this); // fflush(stderr); // #endif // UErrorCode subStatus = U_ZERO_ERROR; // int32_t len; // char kwBuf[128] = ""; // const UChar *kw; // /* fFillin = */ getByKey2(key, U_DEFAULT_KEY, subStatus); // kw = ures_getString(fFillin, &len, &subStatus); // if(len>126) { // too big // len = 0; // } // if(U_SUCCESS(subStatus) && (len>0)) { // u_UCharsToChars(kw, kwBuf, len+1); // if(*kwBuf && uprv_strcmp(kwBuf,subKey)) { // #if defined (U_DEBUG_CALDATA) // fprintf(stderr, "%p: trying %s/format/default -> \"%s\"\n",this, key, kwBuf); // #endif // // now try again with the default // status = U_ZERO_ERROR; // /* fFillin = */ getByKey2(key, kwBuf, status); // } // #if defined (U_DEBUG_CALDATA) // } else { // fprintf(stderr, "%p: could not load %s/format/default - fail out (%s)\n",this, key, kwBuf, u_errorName(status)); // #endif // } // } return fFillin; }