-
-/**
- * Set whether or not scientific notation is used.
- * @param useScientific TRUE if this object formats and parses scientific
- * notation
- * @see #isScientificNotation
- * @see #getMinimumExponentDigits
- * @see #setMinimumExponentDigits
- * @see #isExponentSignAlwaysShown
- * @see #setExponentSignAlwaysShown
- */
-void DecimalFormat::setScientificNotation(UBool useScientific) {
- fUseExponentialNotation = useScientific;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-/**
- * Return the minimum exponent digits that will be shown.
- * @return the minimum exponent digits that will be shown
- * @see #setScientificNotation
- * @see #isScientificNotation
- * @see #setMinimumExponentDigits
- * @see #isExponentSignAlwaysShown
- * @see #setExponentSignAlwaysShown
- */
-int8_t DecimalFormat::getMinimumExponentDigits() const {
- return fMinExponentDigits;
-}
-
-/**
- * Set the minimum exponent digits that will be shown. This has no
- * effect unless scientific notation is in use.
- * @param minExpDig a value >= 1 indicating the fewest exponent digits
- * that will be shown. Values less than 1 will be treated as 1.
- * @see #setScientificNotation
- * @see #isScientificNotation
- * @see #getMinimumExponentDigits
- * @see #isExponentSignAlwaysShown
- * @see #setExponentSignAlwaysShown
- */
-void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
- fMinExponentDigits = (int8_t)((minExpDig > 0) ? minExpDig : 1);
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-/**
- * Return whether the exponent sign is always shown.
- * @return TRUE if the exponent is always prefixed with either the
- * localized minus sign or the localized plus sign, false if only negative
- * exponents are prefixed with the localized minus sign.
- * @see #setScientificNotation
- * @see #isScientificNotation
- * @see #setMinimumExponentDigits
- * @see #getMinimumExponentDigits
- * @see #setExponentSignAlwaysShown
- */
-UBool DecimalFormat::isExponentSignAlwaysShown() {
- return fExponentSignAlwaysShown;
-}
-
-/**
- * Set whether the exponent sign is always shown. This has no effect
- * unless scientific notation is in use.
- * @param expSignAlways TRUE if the exponent is always prefixed with either
- * the localized minus sign or the localized plus sign, false if only
- * negative exponents are prefixed with the localized minus sign.
- * @see #setScientificNotation
- * @see #isScientificNotation
- * @see #setMinimumExponentDigits
- * @see #getMinimumExponentDigits
- * @see #isExponentSignAlwaysShown
- */
-void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
- fExponentSignAlwaysShown = expSignAlways;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-//------------------------------------------------------------------------------
-// Gets the grouping size of the number pattern. For example, thousand or 10
-// thousand groupings.
-
-int32_t
-DecimalFormat::getGroupingSize() const
-{
- return fGroupingSize;
-}
-
-//------------------------------------------------------------------------------
-// Gets the grouping size of the number pattern.
-
-void
-DecimalFormat::setGroupingSize(int32_t newValue)
-{
- fGroupingSize = newValue;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-//------------------------------------------------------------------------------
-
-int32_t
-DecimalFormat::getSecondaryGroupingSize() const
-{
- return fGroupingSize2;
-}
-
-//------------------------------------------------------------------------------
-
-void
-DecimalFormat::setSecondaryGroupingSize(int32_t newValue)
-{
- fGroupingSize2 = newValue;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-//------------------------------------------------------------------------------
-// Checks if to show the decimal separator.
-
-UBool
-DecimalFormat::isDecimalSeparatorAlwaysShown() const
-{
- return fDecimalSeparatorAlwaysShown;
-}
-
-//------------------------------------------------------------------------------
-// Sets to always show the decimal separator.
-
-void
-DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue)
-{
- fDecimalSeparatorAlwaysShown = newValue;
-#if UCONFIG_FORMAT_FASTPATHS_49
- handleChanged();
-#endif
-}
-
-//------------------------------------------------------------------------------
-// Emits the pattern of this DecimalFormat instance.
-
-UnicodeString&
-DecimalFormat::toPattern(UnicodeString& result) const
-{
- return toPattern(result, FALSE);
-}
-
-//------------------------------------------------------------------------------
-// Emits the localized pattern this DecimalFormat instance.
-
-UnicodeString&
-DecimalFormat::toLocalizedPattern(UnicodeString& result) const
-{
- return toPattern(result, TRUE);
-}
-
-//------------------------------------------------------------------------------
-/**
- * Expand the affix pattern strings into the expanded affix strings. If any
- * affix pattern string is null, do not expand it. This method should be
- * called any time the symbols or the affix patterns change in order to keep
- * the expanded affix strings up to date.
- * This method also will be called before formatting if format currency
- * plural names, since the plural name is not a static one, it is
- * based on the currency plural count, the affix will be known only
- * after the currency plural count is know.
- * In which case, the parameter
- * 'pluralCount' will be a non-null currency plural count.
- * In all other cases, the 'pluralCount' is null, which means it is not needed.
- */
-void DecimalFormat::expandAffixes(const UnicodeString* pluralCount) {
- FieldPositionHandler none;
- if (fPosPrefixPattern != 0) {
- expandAffix(*fPosPrefixPattern, fPositivePrefix, 0, none, FALSE, pluralCount);
- }
- if (fPosSuffixPattern != 0) {
- expandAffix(*fPosSuffixPattern, fPositiveSuffix, 0, none, FALSE, pluralCount);
- }
- if (fNegPrefixPattern != 0) {
- expandAffix(*fNegPrefixPattern, fNegativePrefix, 0, none, FALSE, pluralCount);
- }
- if (fNegSuffixPattern != 0) {
- expandAffix(*fNegSuffixPattern, fNegativeSuffix, 0, none, FALSE, pluralCount);
- }
-#ifdef FMT_DEBUG
- UnicodeString s;
- s.append(UnicodeString("["))
- .append(DEREFSTR(fPosPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fPosSuffixPattern))
- .append((UnicodeString)";") .append(DEREFSTR(fNegPrefixPattern)).append((UnicodeString)"|").append(DEREFSTR(fNegSuffixPattern))
- .append((UnicodeString)"]->[")
- .append(fPositivePrefix).append((UnicodeString)"|").append(fPositiveSuffix)
- .append((UnicodeString)";") .append(fNegativePrefix).append((UnicodeString)"|").append(fNegativeSuffix)
- .append((UnicodeString)"]\n");
- debugout(s);
-#endif
-}
-
-/**
- * Expand an affix pattern into an affix string. All characters in the
- * pattern are literal unless prefixed by kQuote. The following characters
- * after kQuote are recognized: PATTERN_PERCENT, PATTERN_PER_MILLE,
- * PATTERN_MINUS, and kCurrencySign. If kCurrencySign is doubled (kQuote +
- * kCurrencySign + kCurrencySign), it is interpreted as an international
- * currency sign. If CURRENCY_SIGN is tripled, it is interpreted as
- * currency plural long names, such as "US Dollars".
- * Any other character after a kQuote represents itself.
- * kQuote must be followed by another character; kQuote may not occur by
- * itself at the end of the pattern.
- *
- * This method is used in two distinct ways. First, it is used to expand
- * the stored affix patterns into actual affixes. For this usage, doFormat
- * must be false. Second, it is used to expand the stored affix patterns
- * given a specific number (doFormat == true), for those rare cases in
- * which a currency format references a ChoiceFormat (e.g., en_IN display
- * name for INR). The number itself is taken from digitList.
- *
- * When used in the first way, this method has a side effect: It sets
- * currencyChoice to a ChoiceFormat object, if the currency's display name
- * in this locale is a ChoiceFormat pattern (very rare). It only does this
- * if currencyChoice is null to start with.
- *
- * @param pattern the non-null, fPossibly empty pattern
- * @param affix string to receive the expanded equivalent of pattern.
- * Previous contents are deleted.
- * @param doFormat if false, then the pattern will be expanded, and if a
- * currency symbol is encountered that expands to a ChoiceFormat, the
- * currencyChoice member variable will be initialized if it is null. If
- * doFormat is true, then it is assumed that the currencyChoice has been
- * created, and it will be used to format the value in digitList.
- * @param pluralCount the plural count. It is only used for currency
- * plural format. In which case, it is the plural
- * count of the currency amount. For example,
- * in en_US, it is the singular "one", or the plural
- * "other". For all other cases, it is null, and
- * is not being used.
- */
-void DecimalFormat::expandAffix(const UnicodeString& pattern,
- UnicodeString& affix,
- double number,
- FieldPositionHandler& handler,
- UBool doFormat,
- const UnicodeString* pluralCount) const {
- affix.remove();
- for (int i=0; i<pattern.length(); ) {
- UChar32 c = pattern.char32At(i);
- i += U16_LENGTH(c);
- if (c == kQuote) {
- c = pattern.char32At(i);
- i += U16_LENGTH(c);
- int beginIdx = affix.length();
- switch (c) {
- case kCurrencySign: {
- // As of ICU 2.2 we use the currency object, and
- // ignore the currency symbols in the DFS, unless
- // we have a null currency object. This occurs if
- // resurrecting a pre-2.2 object or if the user
- // sets a custom DFS.
- UBool intl = i<pattern.length() &&
- pattern.char32At(i) == kCurrencySign;
- UBool plural = FALSE;
- if (intl) {
- ++i;
- plural = i<pattern.length() &&
- pattern.char32At(i) == kCurrencySign;
- if (plural) {
- intl = FALSE;
- ++i;
- }
- }
- const UChar* currencyUChars = getCurrency();
- if (currencyUChars[0] != 0) {
- UErrorCode ec = U_ZERO_ERROR;
- if (plural && pluralCount != NULL) {
- // plural name is only needed when pluralCount != null,
- // which means when formatting currency plural names.
- // For other cases, pluralCount == null,
- // and plural names are not needed.
- int32_t len;
- CharString pluralCountChar;
- pluralCountChar.appendInvariantChars(*pluralCount, ec);
- UBool isChoiceFormat;
- const UChar* s = ucurr_getPluralName(currencyUChars,
- fSymbols != NULL ? fSymbols->getLocale().getName() :
- Locale::getDefault().getName(), &isChoiceFormat,
- pluralCountChar.data(), &len, &ec);
- affix += UnicodeString(s, len);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- } else if(intl) {
- affix.append(currencyUChars, -1);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- } else {
- int32_t len;
- UBool isChoiceFormat;
- // If fSymbols is NULL, use default locale
- const UChar* s = ucurr_getName(currencyUChars,
- fSymbols != NULL ? fSymbols->getLocale().getName() : Locale::getDefault().getName(),
- UCURR_SYMBOL_NAME, &isChoiceFormat, &len, &ec);
- if (isChoiceFormat) {
- // Two modes here: If doFormat is false, we set up
- // currencyChoice. If doFormat is true, we use the
- // previously created currencyChoice to format the
- // value in digitList.
- if (!doFormat) {
- // If the currency is handled by a ChoiceFormat,
- // then we're not going to use the expanded
- // patterns. Instantiate the ChoiceFormat and
- // return.
- if (fCurrencyChoice == NULL) {
- // TODO Replace double-check with proper thread-safe code
- ChoiceFormat* fmt = new ChoiceFormat(UnicodeString(s), ec);
- if (U_SUCCESS(ec)) {
- umtx_lock(NULL);
- if (fCurrencyChoice == NULL) {
- // Cast away const
- ((DecimalFormat*)this)->fCurrencyChoice = fmt;
- fmt = NULL;
- }
- umtx_unlock(NULL);
- delete fmt;
- }
- }
- // We could almost return null or "" here, since the
- // expanded affixes are almost not used at all
- // in this situation. However, one method --
- // toPattern() -- still does use the expanded
- // affixes, in order to set up a padding
- // pattern. We use the CURRENCY_SIGN as a
- // placeholder.
- affix.append(kCurrencySign);
- } else {
- if (fCurrencyChoice != NULL) {
- FieldPosition pos(0); // ignored
- if (number < 0) {
- number = -number;
- }
- fCurrencyChoice->format(number, affix, pos);
- } else {
- // We only arrive here if the currency choice
- // format in the locale data is INVALID.
- affix.append(currencyUChars, -1);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- }
- }
- continue;
- }
- affix += UnicodeString(s, len);
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- }
- } else {
- if(intl) {
- affix += getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
- } else {
- affix += getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
- }
- handler.addAttribute(kCurrencyField, beginIdx, affix.length());
- }
- break;
- }
- case kPatternPercent:
- affix += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
- handler.addAttribute(kPercentField, beginIdx, affix.length());
- break;
- case kPatternPerMill:
- affix += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
- handler.addAttribute(kPermillField, beginIdx, affix.length());
- break;
- case kPatternPlus:
- affix += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
- handler.addAttribute(kSignField, beginIdx, affix.length());
- break;
- case kPatternMinus:
- affix += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
- handler.addAttribute(kSignField, beginIdx, affix.length());
- break;
- default:
- affix.append(c);
- break;
- }
- }
- else {
- affix.append(c);
- }
- }
-}
-
-/**
- * Append an affix to the given StringBuffer.
- * @param buf buffer to append to
- * @param isNegative
- * @param isPrefix
- */
-int32_t DecimalFormat::appendAffix(UnicodeString& buf, double number,
- FieldPositionHandler& handler,
- UBool isNegative, UBool isPrefix) const {
- // plural format precedes choice format
- if (fCurrencyChoice != 0 &&
- fCurrencySignCount != fgCurrencySignCountInPluralFormat) {
- const UnicodeString* affixPat;
- if (isPrefix) {
- affixPat = isNegative ? fNegPrefixPattern : fPosPrefixPattern;
- } else {
- affixPat = isNegative ? fNegSuffixPattern : fPosSuffixPattern;
- }
- if (affixPat) {
- UnicodeString affixBuf;
- expandAffix(*affixPat, affixBuf, number, handler, TRUE, NULL);
- buf.append(affixBuf);
- return affixBuf.length();
- }
- // else someone called a function that reset the pattern.
- }
-
- const UnicodeString* affix;
- if (fCurrencySignCount == fgCurrencySignCountInPluralFormat) {
- UnicodeString pluralCount = fCurrencyPluralInfo->getPluralRules()->select(number);
- AffixesForCurrency* oneSet;
- if (fStyle == UNUM_CURRENCY_PLURAL) {
- oneSet = (AffixesForCurrency*)fPluralAffixesForCurrency->get(pluralCount);
- } else {
- oneSet = (AffixesForCurrency*)fAffixesForCurrency->get(pluralCount);
- }
- if (isPrefix) {
- affix = isNegative ? &oneSet->negPrefixForCurrency :
- &oneSet->posPrefixForCurrency;
- } else {
- affix = isNegative ? &oneSet->negSuffixForCurrency :
- &oneSet->posSuffixForCurrency;
- }
- } else {
- if (isPrefix) {
- affix = isNegative ? &fNegativePrefix : &fPositivePrefix;
- } else {
- affix = isNegative ? &fNegativeSuffix : &fPositiveSuffix;
- }
- }
-
- int32_t begin = (int) buf.length();
-
- buf.append(*affix);
-
- if (handler.isRecording()) {
- int32_t offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kCurrencySymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kCurrencySymbol);
- handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol);
- handler.addAttribute(kCurrencyField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
- handler.addAttribute(kSignField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
- handler.addAttribute(kPercentField, begin + offset, begin + offset + aff.length());
- }
-
- offset = (int) (*affix).indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol));
- if (offset > -1) {
- UnicodeString aff = getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
- handler.addAttribute(kPermillField, begin + offset, begin + offset + aff.length());
- }
- }
- return affix->length();
-}
-
-/**
- * Appends an affix pattern to the given StringBuffer, quoting special
- * characters as needed. Uses the internal affix pattern, if that exists,
- * or the literal affix, if the internal affix pattern is null. The
- * appended string will generate the same affix pattern (or literal affix)
- * when passed to toPattern().
- *
- * @param appendTo the affix string is appended to this
- * @param affixPattern a pattern such as fPosPrefixPattern; may be null
- * @param expAffix a corresponding expanded affix, such as fPositivePrefix.
- * Ignored unless affixPattern is null. If affixPattern is null, then
- * expAffix is appended as a literal affix.
- * @param localized true if the appended pattern should contain localized
- * pattern characters; otherwise, non-localized pattern chars are appended
- */
-void DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
- const UnicodeString* affixPattern,
- const UnicodeString& expAffix,
- UBool localized) const {
- if (affixPattern == 0) {
- appendAffixPattern(appendTo, expAffix, localized);
- } else {
- int i;
- for (int pos=0; pos<affixPattern->length(); pos=i) {
- i = affixPattern->indexOf(kQuote, pos);
- if (i < 0) {
- UnicodeString s;
- affixPattern->extractBetween(pos, affixPattern->length(), s);
- appendAffixPattern(appendTo, s, localized);
- break;
- }
- if (i > pos) {
- UnicodeString s;
- affixPattern->extractBetween(pos, i, s);
- appendAffixPattern(appendTo, s, localized);
- }
- UChar32 c = affixPattern->char32At(++i);
- ++i;
- if (c == kQuote) {
- appendTo.append(c).append(c);
- // Fall through and append another kQuote below
- } else if (c == kCurrencySign &&
- i<affixPattern->length() &&
- affixPattern->char32At(i) == kCurrencySign) {
- ++i;
- appendTo.append(c).append(c);
- } else if (localized) {
- switch (c) {
- case kPatternPercent:
- appendTo += getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
- break;
- case kPatternPerMill:
- appendTo += getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
- break;
- case kPatternPlus:
- appendTo += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
- break;
- case kPatternMinus:
- appendTo += getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
- break;
- default:
- appendTo.append(c);
- }
- } else {
- appendTo.append(c);
- }
- }
- }
-}
-
-/**
- * Append an affix to the given StringBuffer, using quotes if
- * there are special characters. Single quotes themselves must be
- * escaped in either case.
- */
-void
-DecimalFormat::appendAffixPattern(UnicodeString& appendTo,
- const UnicodeString& affix,
- UBool localized) const {
- UBool needQuote;
- if(localized) {
- needQuote = affix.indexOf(getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPercentSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPerMillSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kDigitSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol)) >= 0
- || affix.indexOf(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) >= 0
- || affix.indexOf(kCurrencySign) >= 0;
- }
- else {
- needQuote = affix.indexOf(kPatternZeroDigit) >= 0
- || affix.indexOf(kPatternGroupingSeparator) >= 0
- || affix.indexOf(kPatternDecimalSeparator) >= 0
- || affix.indexOf(kPatternPercent) >= 0
- || affix.indexOf(kPatternPerMill) >= 0
- || affix.indexOf(kPatternDigit) >= 0
- || affix.indexOf(kPatternSeparator) >= 0
- || affix.indexOf(kPatternExponent) >= 0
- || affix.indexOf(kPatternPlus) >= 0
- || affix.indexOf(kPatternMinus) >= 0
- || affix.indexOf(kCurrencySign) >= 0;
- }
- if (needQuote)
- appendTo += (UChar)0x0027 /*'\''*/;
- if (affix.indexOf((UChar)0x0027 /*'\''*/) < 0)
- appendTo += affix;
- else {
- for (int32_t j = 0; j < affix.length(); ) {
- UChar32 c = affix.char32At(j);
- j += U16_LENGTH(c);
- appendTo += c;
- if (c == 0x0027 /*'\''*/)
- appendTo += c;
- }
- }
- if (needQuote)
- appendTo += (UChar)0x0027 /*'\''*/;
-}
-
-//------------------------------------------------------------------------------
-
-UnicodeString&
-DecimalFormat::toPattern(UnicodeString& result, UBool localized) const
-{
- if (fStyle == UNUM_CURRENCY_PLURAL) {
- // the prefix or suffix pattern might not be defined yet,
- // so they can not be synthesized,
- // instead, get them directly.
- // but it might not be the actual pattern used in formatting.
- // the actual pattern used in formatting depends on the
- // formatted number's plural count.
- result = fFormatPattern;
- return result;
- }
- result.remove();
- UChar32 zero, sigDigit = kPatternSignificantDigit;
- UnicodeString digit, group;
- int32_t i;
- int32_t roundingDecimalPos = 0; // Pos of decimal in roundingDigits
- UnicodeString roundingDigits;
- int32_t padPos = (fFormatWidth > 0) ? fPadPosition : -1;
- UnicodeString padSpec;
- UBool useSigDig = areSignificantDigitsUsed();
-
- if (localized) {
- digit.append(getConstSymbol(DecimalFormatSymbols::kDigitSymbol));
- group.append(getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol));
- zero = getConstSymbol(DecimalFormatSymbols::kZeroDigitSymbol).char32At(0);
- if (useSigDig) {
- sigDigit = getConstSymbol(DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0);
- }
- }
- else {
- digit.append((UChar)kPatternDigit);
- group.append((UChar)kPatternGroupingSeparator);
- zero = (UChar32)kPatternZeroDigit;
- }
- if (fFormatWidth > 0) {
- if (localized) {
- padSpec.append(getConstSymbol(DecimalFormatSymbols::kPadEscapeSymbol));
- }
- else {
- padSpec.append((UChar)kPatternPadEscape);
- }
- padSpec.append(fPad);
- }
- if (fRoundingIncrement != NULL) {
- for(i=0; i<fRoundingIncrement->getCount(); ++i) {
- roundingDigits.append(zero+(fRoundingIncrement->getDigitValue(i))); // Convert to Unicode digit
- }
- roundingDecimalPos = fRoundingIncrement->getDecimalAt();
- }
- for (int32_t part=0; part<2; ++part) {
- if (padPos == kPadBeforePrefix) {
- result.append(padSpec);
- }
- appendAffixPattern(result,
- (part==0 ? fPosPrefixPattern : fNegPrefixPattern),
- (part==0 ? fPositivePrefix : fNegativePrefix),
- localized);
- if (padPos == kPadAfterPrefix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- int32_t sub0Start = result.length();
- int32_t g = isGroupingUsed() ? _max(0, fGroupingSize) : 0;
- if (g > 0 && fGroupingSize2 > 0 && fGroupingSize2 != fGroupingSize) {
- g += fGroupingSize2;
- }
- int32_t maxDig = 0, minDig = 0, maxSigDig = 0;
- if (useSigDig) {
- minDig = getMinimumSignificantDigits();
- maxDig = maxSigDig = getMaximumSignificantDigits();
- } else {
- minDig = getMinimumIntegerDigits();
- maxDig = getMaximumIntegerDigits();
- }
- if (fUseExponentialNotation) {
- if (maxDig > kMaxScientificIntegerDigits) {
- maxDig = 1;
- }
- } else if (useSigDig) {
- maxDig = _max(maxDig, g+1);
- } else {
- maxDig = _max(_max(g, getMinimumIntegerDigits()),
- roundingDecimalPos) + 1;
- }
- for (i = maxDig; i > 0; --i) {
- if (!fUseExponentialNotation && i<maxDig &&
- isGroupingPosition(i)) {
- result.append(group);
- }
- if (useSigDig) {
- // #@,@### (maxSigDig == 5, minSigDig == 2)
- // 65 4321 (1-based pos, count from the right)
- // Use # if pos > maxSigDig or 1 <= pos <= (maxSigDig - minSigDig)
- // Use @ if (maxSigDig - minSigDig) < pos <= maxSigDig
- if (maxSigDig >= i && i > (maxSigDig - minDig)) {
- result.append(sigDigit);
- } else {
- result.append(digit);
- }
- } else {
- if (! roundingDigits.isEmpty()) {
- int32_t pos = roundingDecimalPos - i;
- if (pos >= 0 && pos < roundingDigits.length()) {
- result.append((UChar) (roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
- continue;
- }
- }
- if (i<=minDig) {
- result.append(zero);
- } else {
- result.append(digit);
- }
- }
- }
- if (!useSigDig) {
- if (getMaximumFractionDigits() > 0 || fDecimalSeparatorAlwaysShown) {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol);
- }
- else {
- result.append((UChar)kPatternDecimalSeparator);
- }
- }
- int32_t pos = roundingDecimalPos;
- for (i = 0; i < getMaximumFractionDigits(); ++i) {
- if (! roundingDigits.isEmpty() && pos < roundingDigits.length()) {
- if (pos < 0) {
- result.append(zero);
- }
- else {
- result.append((UChar)(roundingDigits.char32At(pos) - kPatternZeroDigit + zero));
- }
- ++pos;
- continue;
- }
- if (i<getMinimumFractionDigits()) {
- result.append(zero);
- }
- else {
- result.append(digit);
- }
- }
- }
- if (fUseExponentialNotation) {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kExponentialSymbol);
- }
- else {
- result.append((UChar)kPatternExponent);
- }
- if (fExponentSignAlwaysShown) {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
- }
- else {
- result.append((UChar)kPatternPlus);
- }
- }
- for (i=0; i<fMinExponentDigits; ++i) {
- result.append(zero);
- }
- }
- if (! padSpec.isEmpty() && !fUseExponentialNotation) {
- int32_t add = fFormatWidth - result.length() + sub0Start
- - ((part == 0)
- ? fPositivePrefix.length() + fPositiveSuffix.length()
- : fNegativePrefix.length() + fNegativeSuffix.length());
- while (add > 0) {
- result.insert(sub0Start, digit);
- ++maxDig;
- --add;
- // Only add a grouping separator if we have at least
- // 2 additional characters to be added, so we don't
- // end up with ",###".
- if (add>1 && isGroupingPosition(maxDig)) {
- result.insert(sub0Start, group);
- --add;
- }
- }
- }
- if (fPadPosition == kPadBeforeSuffix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- if (part == 0) {
- appendAffixPattern(result, fPosSuffixPattern, fPositiveSuffix, localized);
- if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- UBool isDefault = FALSE;
- if ((fNegSuffixPattern == fPosSuffixPattern && // both null
- fNegativeSuffix == fPositiveSuffix)
- || (fNegSuffixPattern != 0 && fPosSuffixPattern != 0 &&
- *fNegSuffixPattern == *fPosSuffixPattern))
- {
- if (fNegPrefixPattern != NULL && fPosPrefixPattern != NULL)
- {
- int32_t length = fPosPrefixPattern->length();
- isDefault = fNegPrefixPattern->length() == (length+2) &&
- (*fNegPrefixPattern)[(int32_t)0] == kQuote &&
- (*fNegPrefixPattern)[(int32_t)1] == kPatternMinus &&
- fNegPrefixPattern->compare(2, length, *fPosPrefixPattern, 0, length) == 0;
- }
- if (!isDefault &&
- fNegPrefixPattern == NULL && fPosPrefixPattern == NULL)
- {
- int32_t length = fPositivePrefix.length();
- isDefault = fNegativePrefix.length() == (length+1) &&
- fNegativePrefix.compare(getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol)) == 0 &&
- fNegativePrefix.compare(1, length, fPositivePrefix, 0, length) == 0;
- }
- }
- if (isDefault) {
- break; // Don't output default negative subpattern
- } else {
- if (localized) {
- result += getConstSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol);
- }
- else {
- result.append((UChar)kPatternSeparator);
- }
- }
- } else {
- appendAffixPattern(result, fNegSuffixPattern, fNegativeSuffix, localized);
- if (fPadPosition == kPadAfterSuffix && ! padSpec.isEmpty()) {
- result.append(padSpec);
- }
- }