Пример #1
0
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);
}
Пример #2
0
/* {{{ ResourceBundle_ctor */
static int resourcebundle_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_constructor)
{
	const char *bundlename;
	size_t		bundlename_len = 0;
	const char *locale;
	size_t		locale_len = 0;
	zend_bool	fallback = 1;
	int         zpp_flags = is_constructor ? ZEND_PARSE_PARAMS_THROW : 0;

	zval                  *object = return_value;
	ResourceBundle_object *rb = Z_INTL_RESOURCEBUNDLE_P( object );

	intl_error_reset( NULL );

	if( zend_parse_parameters_ex( zpp_flags, ZEND_NUM_ARGS(), "s!s!|b",
		&locale, &locale_len, &bundlename, &bundlename_len, &fallback ) == FAILURE )
	{
		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
			"resourcebundle_ctor: unable to parse input parameters", 0 );
		return FAILURE;
	}

	INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len);

	if (locale == NULL) {
		locale = intl_locale_get_default();
	}

	if (bundlename_len >= MAXPATHLEN) {
		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,	"Bundle name too long", 0 );
		zval_ptr_dtor(return_value);
		ZVAL_NULL(return_value);
		return FAILURE;
	}

	if (fallback) {
		rb->me = ures_open(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
	} else {
		rb->me = ures_openDirect(bundlename, locale, &INTL_DATA_ERROR_CODE(rb));
	}

	INTL_CTOR_CHECK_STATUS(rb, "resourcebundle_ctor: Cannot load libICU resource bundle");

	if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING ||
			INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
		char *pbuf;
		intl_errors_set_code(NULL, INTL_DATA_ERROR_CODE(rb));
		spprintf(&pbuf, 0, "resourcebundle_ctor: Cannot load libICU resource "
				"'%s' without fallback from %s to %s",
				bundlename ? bundlename : "(default data)", locale,
				ures_getLocaleByType(
					rb->me, ULOC_ACTUAL_LOCALE, &INTL_DATA_ERROR_CODE(rb)));
		intl_errors_set_custom_msg(INTL_DATA_ERROR_P(rb), pbuf, 1);
		efree(pbuf);
		return FAILURE;
	}

	return SUCCESS;
}
Пример #3
0
static UBool isRoot(const UResourceBundle* rb, UErrorCode& status) {
  const char* actualLocale = ures_getLocaleByType(
      rb, ULOC_ACTUAL_LOCALE, &status);
  if (U_FAILURE(status)) {
    return FALSE;
  }
  return uprv_strcmp(actualLocale, gRoot) == 0;
}
Пример #4
0
/* {{{ resourcebundle_array_fetch */
static void resourcebundle_array_fetch(zval *object, zval *offset, zval *return_value, int fallback)
{
	int32_t     meindex = 0;
	char *      mekey = NULL;
    zend_bool    is_numeric = 0;
	char         *pbuf;
	ResourceBundle_object *rb;

	intl_error_reset( NULL );
	RESOURCEBUNDLE_METHOD_FETCH_OBJECT;

	if(Z_TYPE_P(offset) == IS_LONG) {
		is_numeric = 1;
		meindex = (int32_t)Z_LVAL_P(offset);
		rb->child = ures_getByIndex( rb->me, meindex, rb->child, &INTL_DATA_ERROR_CODE(rb) );
	} else if(Z_TYPE_P(offset) == IS_STRING) {
		mekey = Z_STRVAL_P(offset);
		rb->child = ures_getByKey(rb->me, mekey, rb->child, &INTL_DATA_ERROR_CODE(rb) );
	} else {
		intl_errors_set(INTL_DATA_ERROR_P(rb), U_ILLEGAL_ARGUMENT_ERROR,
			"resourcebundle_get: index should be integer or string", 0);
		RETURN_NULL();
	}

	intl_error_set_code( NULL, INTL_DATA_ERROR_CODE(rb) );
	if (U_FAILURE(INTL_DATA_ERROR_CODE(rb))) {
		if (is_numeric) {
			spprintf( &pbuf, 0, "Cannot load resource element %d", meindex );
		} else {
			spprintf( &pbuf, 0, "Cannot load resource element '%s'", mekey );
		}
		intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 );
		efree(pbuf);
		RETURN_NULL();
	}

	if (!fallback && (INTL_DATA_ERROR_CODE(rb) == U_USING_FALLBACK_WARNING || INTL_DATA_ERROR_CODE(rb) == U_USING_DEFAULT_WARNING)) {
		UErrorCode icuerror;
		const char * locale = ures_getLocaleByType( rb->me, ULOC_ACTUAL_LOCALE, &icuerror );
		if (is_numeric) {
			spprintf( &pbuf, 0, "Cannot load element %d without fallback from to %s", meindex, locale );
		} else {
			spprintf( &pbuf, 0, "Cannot load element '%s' without fallback from to %s", mekey, locale );
		}
		intl_errors_set_custom_msg( INTL_DATA_ERROR_P(rb), pbuf, 1 );
		efree(pbuf);
		RETURN_NULL();
	}

	resourcebundle_extract_value( return_value, rb );
}
Пример #5
0
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;
}
Пример #6
0
static void TestGetLocaleByType(void) {
    static const struct {
        const char *requestedLocale;
        const char *resourceKey;
        const char *validLocale;
        const char *actualLocale;
    } test[] = {
        { "te_IN_BLAH", "string_only_in_te_IN", "te_IN", "te_IN" },
        { "te_IN_BLAH", "string_only_in_te", "te_IN", "te" },
        { "te_IN_BLAH", "string_only_in_Root", "te_IN", "root" },
        { "te_IN_BLAH_01234567890_01234567890_01234567890_01234567890_01234567890_01234567890", "array_2d_only_in_Root", "te_IN", "root" },
        { "te_IN_BLAH@currency=euro", "array_2d_only_in_te_IN", "te_IN", "te_IN" },
        { "te_IN_BLAH@collation=phonebook;calendar=thai", "array_2d_only_in_te", "te_IN", "te" }
    };
    
    UErrorCode status = U_ZERO_ERROR;
    
    UResourceBundle *rb = NULL;
    UResourceBundle *res = NULL;
    const char* testdatapath = loadTestData(&status);
    int32_t i = 0;
    const char *locale = NULL;
    
    if(U_FAILURE(status))
    {
        log_data_err("Could not load testdata.dat %s\n", u_errorName(status));
        return;
    }
    
    for(i = 0; i < UPRV_LENGTHOF(test); i++) {
        rb = ures_open(testdatapath, test[i].requestedLocale, &status);
        if(U_FAILURE(status))
        {
            log_err("Could not open resource bundle %s (error %s)\n", test[i].requestedLocale, u_errorName(status));
            status = U_ZERO_ERROR;
            continue;
        }
        
        res = ures_getByKey(rb, test[i].resourceKey, res, &status);
        if(U_FAILURE(status))
        {
            log_err("Couldn't find the key %s. Error: %s\n", test[i].resourceKey, u_errorName(status));
            ures_close(rb);
            status = U_ZERO_ERROR;
            continue;
        }

        locale = ures_getLocaleByType(res, ULOC_REQUESTED_LOCALE, &status);
        if(U_SUCCESS(status) && locale != NULL) {
            log_err("Requested locale should return NULL\n");
        }
        status = U_ZERO_ERROR;
        locale = ures_getLocaleByType(res, ULOC_VALID_LOCALE, &status);
        if(!locale || strcmp(locale, test[i].validLocale) != 0) {
            log_err("Expected valid locale to be %s. Got %s\n", test[i].requestedLocale, locale);
        }
        locale = ures_getLocaleByType(res, ULOC_ACTUAL_LOCALE, &status);
        if(!locale || strcmp(locale, test[i].actualLocale) != 0) {
            log_err("Expected actual locale to be %s. Got %s\n", test[i].requestedLocale, locale);
        }
        ures_close(rb);
    }
    ures_close(res);
}
Пример #7
0
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);
            }
        }
    }
}
Пример #8
0
const Locale ResourceBundle::getLocale(ULocDataLocaleType type, UErrorCode &status) const
{
  return ures_getLocaleByType(fResource, type, &status);
}
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);
}
Пример #10
0
NumberFormat*
NumberFormat::makeInstance(const Locale& desiredLocale,
                           EStyles style,
                           UErrorCode& status)
{
    if (U_FAILURE(status)) return NULL;

    if (style < 0 || style >= kStyleCount) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return NULL;
    }

#ifdef U_WINDOWS
    char buffer[8];
    int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);

    // if the locale has "@compat=host", create a host-specific NumberFormat
    if (count > 0 && uprv_strcmp(buffer, "host") == 0) {
        Win32NumberFormat *f = NULL;
        UBool curr = TRUE;

        switch (style) {
        case kNumberStyle:
            curr = FALSE;
            // fall-through

        case kCurrencyStyle:
        case kIsoCurrencyStyle: // do not support plural formatting here
        case kPluralCurrencyStyle:
            f = new Win32NumberFormat(desiredLocale, curr, status);

            if (U_SUCCESS(status)) {
                return f;
            }

            delete f;
            break;

        default:
            break;
        }
    }
#endif

    NumberFormat* f = NULL;
    DecimalFormatSymbols* symbolsToAdopt = NULL;
    UnicodeString pattern;
    UResourceBundle *resource = ures_open((char *)0, desiredLocale.getName(), &status);
    UResourceBundle *numberPatterns = ures_getByKey(resource, DecimalFormat::fgNumberPatterns, NULL, &status);
    NumberingSystem *ns = NULL;
    UBool deleteSymbols = TRUE;
    UHashtable * cache = NULL;
    int32_t hashKey;
    UBool getCache = FALSE;
    UBool deleteNS = FALSE;

    if (U_FAILURE(status)) {
        // We don't appear to have resource data available -- use the last-resort data
        status = U_USING_FALLBACK_WARNING;
        // When the data is unavailable, and locale isn't passed in, last resort data is used.
        symbolsToAdopt = new DecimalFormatSymbols(status);

        // Creates a DecimalFormat instance with the last resort number patterns.
        pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1);
    }
    else {
        // If not all the styled patterns exists for the NumberFormat in this locale,
        // sets the status code to failure and returns nil.
        if (ures_getSize(numberPatterns) < (int32_t)(sizeof(gLastResortNumberPatterns)/sizeof(gLastResortNumberPatterns[0])) -2 ) { //minus 2: ISO and plural
            status = U_INVALID_FORMAT_ERROR;
            goto cleanup;
        }

        // Loads the decimal symbols of the desired locale.
        symbolsToAdopt = new DecimalFormatSymbols(desiredLocale, status);

        int32_t patLen = 0;

        /* for ISOCURRENCYSTYLE and PLURALCURRENCYSTYLE,
         * the pattern is the same as the pattern of CURRENCYSTYLE
         * but by replacing the single currency sign with
         * double currency sign or triple currency sign.
         */
        int styleInNumberPattern = ((style == kIsoCurrencyStyle ||
                                     style == kPluralCurrencyStyle) ?
                                    kCurrencyStyle : style);

        const UChar *patResStr = ures_getStringByIndex(numberPatterns, (int32_t)styleInNumberPattern, &patLen, &status);

        // Creates the specified decimal format style of the desired locale.
        pattern.setTo(TRUE, patResStr, patLen);
    }
    if (U_FAILURE(status) || symbolsToAdopt == NULL) {
        goto cleanup;
    }
    if(style==kCurrencyStyle || style == kIsoCurrencyStyle){
        const UChar* currPattern = symbolsToAdopt->getCurrencyPattern();
        if(currPattern!=NULL){
            pattern.setTo(currPattern, u_strlen(currPattern));
        }
    }

    // Use numbering system cache hashtable
    UMTX_CHECK(&nscacheMutex, (UBool)(cache != NumberingSystem_cache), getCache);
    if (getCache) {
        umtx_lock(&nscacheMutex);
        cache = NumberingSystem_cache;
        umtx_unlock(&nscacheMutex);
    }

    // Check cache we got, create if non-existant
    status = U_ZERO_ERROR;
    if (cache == NULL) {
        cache = uhash_open(uhash_hashLong,
                           uhash_compareLong,
                           NULL,
                           &status);

        if (cache == NULL || U_FAILURE(status)) {
            // cache not created - out of memory
            cache = NULL;
        }
        else {
            // cache created
            uhash_setValueDeleter(cache, deleteNumberingSystem);

            // set final NumberingSystem_cache value
            UHashtable* h = NULL;

            UMTX_CHECK(&nscacheMutex, (UBool)(h != NumberingSystem_cache), getCache);
            if (getCache) {
                umtx_lock(&nscacheMutex);
                h = NumberingSystem_cache;
                umtx_unlock(&nscacheMutex);
            }
            if (h == NULL) {
                umtx_lock(&nscacheMutex);
                NumberingSystem_cache = h = cache;
                cache = NULL;
                ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
                umtx_unlock(&nscacheMutex);
            }

            if(cache != NULL) {
              uhash_close(cache);
            }
            cache = h;
        }
    }

    // Get cached numbering system
    if (cache != NULL) {
        hashKey = desiredLocale.hashCode();

        umtx_lock(&nscacheMutex);
        ns = (NumberingSystem *)uhash_iget(cache, hashKey);
        if (ns == NULL) {
            ns = NumberingSystem::createInstance(desiredLocale,status);
            uhash_iput(cache, hashKey, (void*)ns, &status);
        }
        umtx_unlock(&nscacheMutex);
    }
    else {
        ns = NumberingSystem::createInstance(desiredLocale,status);
        deleteNS = TRUE;
    }

    // check results of getting a numbering system
    if ((ns == NULL) || (U_FAILURE(status))) {
        goto cleanup;
    }

    if (ns->isAlgorithmic()) {
        UnicodeString nsDesc;
        UnicodeString nsRuleSetGroup;
        UnicodeString nsRuleSetName;
        Locale nsLoc;
        URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;

        nsDesc.setTo(ns->getDescription());
        int32_t firstSlash = nsDesc.indexOf(gSlash);
        int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
        if ( lastSlash > firstSlash ) {
            char nsLocID[ULOC_FULLNAME_CAPACITY];

            nsDesc.extract(0,firstSlash,nsLocID,ULOC_FULLNAME_CAPACITY,US_INV);
            nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
            nsRuleSetName.setTo(nsDesc,lastSlash+1);

            nsLoc = Locale::createFromName(nsLocID);

            UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
            if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
                desiredRulesType = URBNF_SPELLOUT;
            }
        } else {
            nsLoc = desiredLocale;
            nsRuleSetName.setTo(nsDesc);
        }

        RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);

        if (U_FAILURE(status) || r == NULL) {
            goto cleanup;
        }
        r->setDefaultRuleSet(nsRuleSetName,status);
        f = (NumberFormat *) r;

    } else {
        // replace single currency sign in the pattern with double currency sign
        // if the style is kIsoCurrencyStyle
        if (style == kIsoCurrencyStyle) {
            pattern.findAndReplace(gSingleCurrencySign, gDoubleCurrencySign);
        }

        f = new DecimalFormat(pattern, symbolsToAdopt, style, status);
        if (U_FAILURE(status) || f == NULL) {
            goto cleanup;
        }
        deleteSymbols = FALSE;
    }

    f->setLocaleIDs(ures_getLocaleByType(numberPatterns, ULOC_VALID_LOCALE, &status),
                    ures_getLocaleByType(numberPatterns, ULOC_ACTUAL_LOCALE, &status));

cleanup:
    ures_close(numberPatterns);
    ures_close(resource);

    if (deleteNS && ns) {
        delete ns;
    }

    if (U_FAILURE(status)) {
        /* If f exists, then it will delete the symbols */
        if (f==NULL) {
            delete symbolsToAdopt;
        }
        else {
            delete f;
        }
        return NULL;
    }
    if (f == NULL || symbolsToAdopt == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
        f = NULL;
    }
    if (deleteSymbols && symbolsToAdopt != NULL) {
        delete symbolsToAdopt;
    }
    return f;
}
Пример #11
0
NumberFormat*
NumberFormat::makeInstance(const Locale& desiredLocale,
                           UNumberFormatStyle style,
                           UBool mustBeDecimalFormat,
                           UErrorCode& status) {
    if (U_FAILURE(status)) return NULL;

    if (style < 0 || style >= UNUM_FORMAT_STYLE_COUNT) {
        status = U_ILLEGAL_ARGUMENT_ERROR;
        return NULL;
    }

    // Some styles are not supported. This is a result of merging
    // the @draft ICU 4.2 NumberFormat::EStyles into the long-existing UNumberFormatStyle.
    // Ticket #8503 is for reviewing/fixing/merging the two relevant implementations:
    // this one and unum_open().
    // The UNUM_PATTERN_ styles are not supported here
    // because this method does not take a pattern string.
    if (!isStyleSupported(style)) {
        status = U_UNSUPPORTED_ERROR;
        return NULL;
    }

#if U_PLATFORM_USES_ONLY_WIN32_API
    if (!mustBeDecimalFormat) {
        char buffer[8];
        int32_t count = desiredLocale.getKeywordValue("compat", buffer, sizeof(buffer), status);

        // if the locale has "@compat=host", create a host-specific NumberFormat
        if (U_SUCCESS(status) && count > 0 && uprv_strcmp(buffer, "host") == 0) {
            Win32NumberFormat *f = NULL;
            UBool curr = TRUE;

            switch (style) {
            case UNUM_DECIMAL:
                curr = FALSE;
                // fall-through

            case UNUM_CURRENCY:
            case UNUM_CURRENCY_ISO: // do not support plural formatting here
            case UNUM_CURRENCY_PLURAL:
                f = new Win32NumberFormat(desiredLocale, curr, status);

                if (U_SUCCESS(status)) {
                    return f;
                }

                delete f;
                break;
            default:
                break;
            }
        }
    }
#endif
    // Use numbering system cache hashtable
    umtx_initOnce(gNSCacheInitOnce, &nscacheInit);

    // Get cached numbering system
    LocalPointer<NumberingSystem> ownedNs;
    NumberingSystem *ns = NULL;
    if (NumberingSystem_cache != NULL) {
        // TODO: Bad hash key usage, see ticket #8504.
        int32_t hashKey = desiredLocale.hashCode();

        Mutex lock(&nscacheMutex);
        ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey);
        if (ns == NULL) {
            ns = NumberingSystem::createInstance(desiredLocale,status);
            uhash_iput(NumberingSystem_cache, hashKey, (void*)ns, &status);
        }
    } else {
        ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status));
        ns = ownedNs.getAlias();
    }

    // check results of getting a numbering system
    if (U_FAILURE(status)) {
        return NULL;
    }

    if (mustBeDecimalFormat && ns->isAlgorithmic()) {
        status = U_UNSUPPORTED_ERROR;
        return NULL;
    }

    LocalPointer<DecimalFormatSymbols> symbolsToAdopt;
    UnicodeString pattern;
    LocalUResourceBundlePointer ownedResource(ures_open(NULL, desiredLocale.getName(), &status));
    if (U_FAILURE(status)) {
        // We don't appear to have resource data available -- use the last-resort data
        status = U_USING_FALLBACK_WARNING;
        // When the data is unavailable, and locale isn't passed in, last resort data is used.
        symbolsToAdopt.adoptInstead(new DecimalFormatSymbols(status));
        if (symbolsToAdopt.isNull()) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return NULL;
        }

        // Creates a DecimalFormat instance with the last resort number patterns.
        pattern.setTo(TRUE, gLastResortNumberPatterns[style], -1);
    }
    else {
        // Loads the decimal symbols of the desired locale.
        symbolsToAdopt.adoptInstead(new DecimalFormatSymbols(desiredLocale, status));
        if (symbolsToAdopt.isNull()) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return NULL;
        }

        UResourceBundle *resource = ownedResource.orphan();
        UResourceBundle *numElements = ures_getByKeyWithFallback(resource, gNumberElements, NULL, &status);
        resource = ures_getByKeyWithFallback(numElements, ns->getName(), resource, &status);
        resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status);
        ownedResource.adoptInstead(resource);

        int32_t patLen = 0;
        const UChar *patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status);

        // Didn't find a pattern specific to the numbering system, so fall back to "latn"
        if ( status == U_MISSING_RESOURCE_ERROR && uprv_strcmp(gLatn,ns->getName())) {
            status = U_ZERO_ERROR;
            resource = ures_getByKeyWithFallback(numElements, gLatn, resource, &status);
            resource = ures_getByKeyWithFallback(resource, gPatterns, resource, &status);
            patResStr = ures_getStringByKeyWithFallback(resource, gFormatKeys[style], &patLen, &status);
        }

        ures_close(numElements);

        // Creates the specified decimal format style of the desired locale.
        pattern.setTo(TRUE, patResStr, patLen);
    }
    if (U_FAILURE(status)) {
        return NULL;
    }
    if(style==UNUM_CURRENCY || style == UNUM_CURRENCY_ISO){
        const UChar* currPattern = symbolsToAdopt->getCurrencyPattern();
        if(currPattern!=NULL){
            pattern.setTo(currPattern, u_strlen(currPattern));
        }
    }


    NumberFormat *f;
    if (ns->isAlgorithmic()) {
        UnicodeString nsDesc;
        UnicodeString nsRuleSetGroup;
        UnicodeString nsRuleSetName;
        Locale nsLoc;
        URBNFRuleSetTag desiredRulesType = URBNF_NUMBERING_SYSTEM;

        nsDesc.setTo(ns->getDescription());
        int32_t firstSlash = nsDesc.indexOf(gSlash);
        int32_t lastSlash = nsDesc.lastIndexOf(gSlash);
        if ( lastSlash > firstSlash ) {
            CharString nsLocID;

            nsLocID.appendInvariantChars(nsDesc.tempSubString(0, firstSlash), status);
            nsRuleSetGroup.setTo(nsDesc,firstSlash+1,lastSlash-firstSlash-1);
            nsRuleSetName.setTo(nsDesc,lastSlash+1);

            nsLoc = Locale::createFromName(nsLocID.data());

            UnicodeString SpelloutRules = UNICODE_STRING_SIMPLE("SpelloutRules");
            if ( nsRuleSetGroup.compare(SpelloutRules) == 0 ) {
                desiredRulesType = URBNF_SPELLOUT;
            }
        } else {
            nsLoc = desiredLocale;
            nsRuleSetName.setTo(nsDesc);
        }

        RuleBasedNumberFormat *r = new RuleBasedNumberFormat(desiredRulesType,nsLoc,status);
        if (r == NULL) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return NULL;
        }
        r->setDefaultRuleSet(nsRuleSetName,status);
        f = r;
    } else {
        // replace single currency sign in the pattern with double currency sign
        // if the style is UNUM_CURRENCY_ISO
        if (style == UNUM_CURRENCY_ISO) {
            pattern.findAndReplace(UnicodeString(TRUE, gSingleCurrencySign, 1),
                                   UnicodeString(TRUE, gDoubleCurrencySign, 2));
        }

        // "new DecimalFormat()" does not adopt the symbols if its memory allocation fails.
        DecimalFormatSymbols *syms = symbolsToAdopt.orphan();
        f = new DecimalFormat(pattern, syms, style, status);
        if (f == NULL) {
            delete syms;
            status = U_MEMORY_ALLOCATION_ERROR;
            return NULL;
        }
    }

    f->setLocaleIDs(ures_getLocaleByType(ownedResource.getAlias(), ULOC_VALID_LOCALE, &status),
                    ures_getLocaleByType(ownedResource.getAlias(), ULOC_ACTUAL_LOCALE, &status));
    if (U_FAILURE(status)) {
        delete f;
        return NULL;
    }
    return f;
}
Пример #12
0
void
DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status, UBool useLastResortData)
{
    if (U_FAILURE(status)) { return; }
    *validLocale = *actualLocale = 0;
    currPattern = NULL;

    // 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));
    const char *nsName;
    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;
    }

    // Open resource bundles
    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;
    }

    // Set locale IDs
    // TODO: Is there a way to do this without depending on the resource bundle instance?
    U_LOCALE_BASED(locBased, *this);
    locBased.setLocaleIDs(
        ures_getLocaleByType(
            numberElementsRes.getAlias(),
            ULOC_VALID_LOCALE, &status),
        ures_getLocaleByType(
            numberElementsRes.getAlias(),
            ULOC_ACTUAL_LOCALE, &status));

    // Now load the rest of the data from the data sink.
    // Start with loading this nsName if it is not Latin.
    DecFmtSymDataSink sink(*this);
    if (uprv_strcmp(nsName, gLatn) != 0) {
        CharString path;
        path.append(gNumberElements, status)
            .append('/', status)
            .append(nsName, status)
            .append('/', status)
            .append(gSymbols, status);
        ures_getAllItemsWithFallback(resource.getAlias(), path.data(), sink, status);

        // If no symbols exist for the given nsName and resource bundle, silently ignore
        // and fall back to Latin.
        if (status == U_MISSING_RESOURCE_ERROR) {
            status = U_ZERO_ERROR;
        } else if (U_FAILURE(status)) {
            return;
        }
    }

    // Continue with Latin if necessary.
    if (!sink.seenAll()) {
        ures_getAllItemsWithFallback(resource.getAlias(), gNumberElementsLatnSymbols, sink, status);
        if (U_FAILURE(status)) { return; }
    }

    // Let the monetary number separators equal the default number separators if necessary.
    sink.resolveMissingMonetarySeparators(fSymbols);

    // 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. */

    //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);
            }
        }
    }
}
Пример #13
0
U_CAPI int32_t U_EXPORT2
ualoc_getAppleParent(const char* localeID,
                     char * parent,
                     int32_t parentCapacity,
                     UErrorCode* err)
{
    UResourceBundle *rb;
    int32_t len;
    UErrorCode tempStatus;
    char locbuf[ULOC_FULLNAME_CAPACITY+1];
    char * foundDoubleUnderscore;

    if (U_FAILURE(*err)) {
        return 0;
    }
    if ( (parent==NULL)? parentCapacity!=0: parentCapacity<0 ) {
        *err = U_ILLEGAL_ARGUMENT_ERROR;
        return 0;
    }
    len = uloc_getBaseName(localeID, locbuf, ULOC_FULLNAME_CAPACITY, err); /* canonicalize and strip keywords */
    if (U_FAILURE(*err)) {
        return 0;
    }
    if (*err == U_STRING_NOT_TERMINATED_WARNING) {
        locbuf[ULOC_FULLNAME_CAPACITY] = 0;
        *err = U_ZERO_ERROR;
    }
    foundDoubleUnderscore = uprv_strstr(locbuf, "__"); /* __ comes from bad/missing subtag or variant */
    if (foundDoubleUnderscore != NULL) {
        *foundDoubleUnderscore = 0; /* terminate at the __ */
        len = uprv_strlen(locbuf);
    }
    if (len >= 2 && uprv_strncmp(locbuf, "zh", 2) == 0) {
        const char ** forceParentPtr = forceParent;
        const char * testCurLoc;
        while ( (testCurLoc = *forceParentPtr++) != NULL ) {
            int cmp = uprv_strcmp(locbuf, testCurLoc);
            if (cmp <= 0) {
                if (cmp == 0) {
                    len = uprv_strlen(*forceParentPtr);
                    if (len < parentCapacity) {
                        uprv_strcpy(parent, *forceParentPtr);
                    } else {
                        *err = U_BUFFER_OVERFLOW_ERROR;
                    }
                    return len;
                }
                break;
            }
            forceParentPtr++;
        }
    }
    tempStatus = U_ZERO_ERROR;
    rb = ures_openDirect(NULL, locbuf, &tempStatus);
    if (U_SUCCESS(tempStatus)) {
        const char * actualLocale = ures_getLocaleByType(rb, ULOC_ACTUAL_LOCALE, &tempStatus);
        if (U_SUCCESS(tempStatus) && uprv_strcmp(locbuf, actualLocale) != 0) {
            // we have followed an alias
            len = uprv_strlen(actualLocale);
            if (len < parentCapacity) {
                uprv_strcpy(parent, actualLocale);
            } else {
                *err = U_BUFFER_OVERFLOW_ERROR;
            }
            ures_close(rb);
            return len;
        }
        tempStatus = U_ZERO_ERROR;
        const UChar * parentUName = ures_getStringByKey(rb, "%%Parent", &len, &tempStatus);
        if (U_SUCCESS(tempStatus) && tempStatus != U_USING_FALLBACK_WARNING) {
            if (len < parentCapacity) {
                u_UCharsToChars(parentUName, parent, len + 1);
            } else {
                *err = U_BUFFER_OVERFLOW_ERROR;
            }
            ures_close(rb);
            return len;
        }
        ures_close(rb);
    }
    len = uloc_getParent(locbuf, parent, parentCapacity, err);
    if (U_SUCCESS(*err) && len == 0) {
        len = 4;
        if (len < parentCapacity) {
            uprv_strcpy(parent, "root");
        } else {
            *err = U_BUFFER_OVERFLOW_ERROR;
        }
    }
    return len;
}
Пример #14
0
U_CFUNC UCollator*
ucol_open_internal(const char *loc,
                   UErrorCode *status)
{
    UErrorCode intStatus = U_ZERO_ERROR;
    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) ||
        !uprv_strcmp(keyBuffer,"default")) { /* Treat 'zz@collation=default' as 'zz'. */
        // no keyword. we try to find the default setting, which will give us the keyword value
        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, collations, status);
    collations = NULL; // We just reused the collations object as collElem.

    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 (U_FAILURE(*status)) {
            goto clean;
        }
        // if we use UCA, real locale is root
        ures_close(b);
        b = ures_open(U_ICUDATA_COLL, "", status);
        ures_close(collElem);
        collElem = ures_open(U_ICUDATA_COLL, "", status);
        if(U_FAILURE(*status)) {
            goto clean;
        }
        result->hasRealData = FALSE;
    } else if(U_SUCCESS(*status)) {
        intStatus = U_ZERO_ERROR;

        binary = ures_getByKey(collElem, "%%CollationBin", NULL, &intStatus);

        if(intStatus == 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(intStatus)) { /* otherwise, we'll pick a collation data that exists */
            int32_t len = 0;
            const uint8_t *inData = ures_getBinary(binary, &len, status);
            if(U_FAILURE(*status)) {
                goto clean;
            }
            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;
            }
        } else { // !U_SUCCESS(binaryStatus)
            if(U_SUCCESS(*status)) {
                *status = intStatus; // propagate underlying error
            }
            goto clean;
        }
        intStatus = U_ZERO_ERROR;
        result->rules = ures_getStringByKey(collElem, "Sequence", &result->rulesLength, &intStatus);
        result->freeRulesOnClose = FALSE;
    } else { /* There is another error, and we're just gonna clean up */
        goto clean;
    }

    intStatus = U_ZERO_ERROR;
    result->ucaRules = ures_getStringByKey(b,"UCARules",NULL,&intStatus);

    if(loc == NULL) {
        loc = ures_getLocaleByType(b, ULOC_ACTUAL_LOCALE, status);
    }
    result->requestedLocale = uprv_strdup(loc);
    /* test for NULL */
    if (result->requestedLocale == NULL) {
        *status = U_MEMORY_ALLOCATION_ERROR;
        goto clean;
    }
    loc = ures_getLocaleByType(collElem, ULOC_ACTUAL_LOCALE, status);
    result->actualLocale = uprv_strdup(loc);
    /* test for NULL */
    if (result->actualLocale == NULL) {
        *status = U_MEMORY_ALLOCATION_ERROR;
        goto clean;
    }
    loc = ures_getLocaleByType(b, ULOC_ACTUAL_LOCALE, status);
    result->validLocale = uprv_strdup(loc);
    /* test for NULL */
    if (result->validLocale == NULL) {
        *status = U_MEMORY_ALLOCATION_ERROR;
        goto clean;
    }

    ures_close(b);
    ures_close(collElem);
    ures_close(binary);
    return result;

clean:
    ures_close(b);
    ures_close(collElem);
    ures_close(binary);
    ucol_close(result);
    return NULL;
}
Пример #15
0
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);
}