| /* |
| ******************************************************************************* |
| * Copyright (C) 1997-2015, International Business Machines Corporation and * |
| * others. All Rights Reserved. * |
| ******************************************************************************* |
| */ |
| |
| #if defined(STARBOARD) |
| #include "starboard/client_porting/poem/assert_poem.h" |
| #include "starboard/client_porting/poem/string_poem.h" |
| #endif // defined(STARBOARD) |
| #include "uassert.h" |
| #include "decimalformatpattern.h" |
| |
| #if !UCONFIG_NO_FORMATTING |
| |
| #include "unicode/dcfmtsym.h" |
| #include "unicode/format.h" |
| #include "unicode/utf16.h" |
| #include "decimalformatpatternimpl.h" |
| |
| |
| #ifdef FMT_DEBUG |
| #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); |
| #else |
| #define debug(x) |
| #endif |
| |
| U_NAMESPACE_BEGIN |
| |
| // TODO: Travis Keep: Copied from numfmt.cpp |
| static int32_t kDoubleIntegerDigits = 309; |
| static int32_t kDoubleFractionDigits = 340; |
| |
| |
| // TODO: Travis Keep: Copied from numfmt.cpp |
| static int32_t gDefaultMaxIntegerDigits = 2000000000; |
| |
| // TODO: Travis Keep: This function was copied from format.cpp |
| static void syntaxError(const UnicodeString& pattern, |
| int32_t pos, |
| UParseError& parseError) { |
| parseError.offset = pos; |
| parseError.line=0; // we are not using line number |
| |
| // for pre-context |
| int32_t start = (pos < U_PARSE_CONTEXT_LEN)? 0 : (pos - (U_PARSE_CONTEXT_LEN-1 |
| /* subtract 1 so that we have room for null*/)); |
| int32_t stop = pos; |
| pattern.extract(start,stop-start,parseError.preContext,0); |
| //null terminate the buffer |
| parseError.preContext[stop-start] = 0; |
| |
| //for post-context |
| start = pos+1; |
| stop = ((pos+U_PARSE_CONTEXT_LEN)<=pattern.length()) ? (pos+(U_PARSE_CONTEXT_LEN-1)) : |
| pattern.length(); |
| pattern.extract(start,stop-start,parseError.postContext,0); |
| //null terminate the buffer |
| parseError.postContext[stop-start]= 0; |
| } |
| |
| DecimalFormatPattern::DecimalFormatPattern() |
| : fMinimumIntegerDigits(1), |
| fMaximumIntegerDigits(gDefaultMaxIntegerDigits), |
| fMinimumFractionDigits(0), |
| fMaximumFractionDigits(3), |
| fUseSignificantDigits(FALSE), |
| fMinimumSignificantDigits(1), |
| fMaximumSignificantDigits(6), |
| fUseExponentialNotation(FALSE), |
| fMinExponentDigits(0), |
| fExponentSignAlwaysShown(FALSE), |
| fCurrencySignCount(fgCurrencySignCountZero), |
| fGroupingUsed(TRUE), |
| fGroupingSize(0), |
| fGroupingSize2(0), |
| fMultiplier(1), |
| fDecimalSeparatorAlwaysShown(FALSE), |
| fFormatWidth(0), |
| fRoundingIncrementUsed(FALSE), |
| fRoundingIncrement(), |
| fPad(kDefaultPad), |
| fNegPatternsBogus(TRUE), |
| fPosPatternsBogus(TRUE), |
| fNegPrefixPattern(), |
| fNegSuffixPattern(), |
| fPosPrefixPattern(), |
| fPosSuffixPattern(), |
| fPadPosition(DecimalFormatPattern::kPadBeforePrefix) { |
| } |
| |
| |
| DecimalFormatPatternParser::DecimalFormatPatternParser() : |
| fZeroDigit(kPatternZeroDigit), |
| fSigDigit(kPatternSignificantDigit), |
| fGroupingSeparator((UChar)kPatternGroupingSeparator), |
| fDecimalSeparator((UChar)kPatternDecimalSeparator), |
| fPercent((UChar)kPatternPercent), |
| fPerMill((UChar)kPatternPerMill), |
| fDigit((UChar)kPatternDigit), |
| fSeparator((UChar)kPatternSeparator), |
| fExponent((UChar)kPatternExponent), |
| fPlus((UChar)kPatternPlus), |
| fMinus((UChar)kPatternMinus), |
| fPadEscape((UChar)kPatternPadEscape) { |
| } |
| |
| void DecimalFormatPatternParser::useSymbols( |
| const DecimalFormatSymbols& symbols) { |
| fZeroDigit = symbols.getConstSymbol( |
| DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); |
| fSigDigit = symbols.getConstSymbol( |
| DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0); |
| fGroupingSeparator = symbols.getConstSymbol( |
| DecimalFormatSymbols::kGroupingSeparatorSymbol); |
| fDecimalSeparator = symbols.getConstSymbol( |
| DecimalFormatSymbols::kDecimalSeparatorSymbol); |
| fPercent = symbols.getConstSymbol( |
| DecimalFormatSymbols::kPercentSymbol); |
| fPerMill = symbols.getConstSymbol( |
| DecimalFormatSymbols::kPerMillSymbol); |
| fDigit = symbols.getConstSymbol( |
| DecimalFormatSymbols::kDigitSymbol); |
| fSeparator = symbols.getConstSymbol( |
| DecimalFormatSymbols::kPatternSeparatorSymbol); |
| fExponent = symbols.getConstSymbol( |
| DecimalFormatSymbols::kExponentialSymbol); |
| fPlus = symbols.getConstSymbol( |
| DecimalFormatSymbols::kPlusSignSymbol); |
| fMinus = symbols.getConstSymbol( |
| DecimalFormatSymbols::kMinusSignSymbol); |
| fPadEscape = symbols.getConstSymbol( |
| DecimalFormatSymbols::kPadEscapeSymbol); |
| } |
| |
| void |
| DecimalFormatPatternParser::applyPatternWithoutExpandAffix( |
| const UnicodeString& pattern, |
| DecimalFormatPattern& out, |
| UParseError& parseError, |
| UErrorCode& status) { |
| if (U_FAILURE(status)) |
| { |
| return; |
| } |
| out = DecimalFormatPattern(); |
| |
| // Clear error struct |
| parseError.offset = -1; |
| parseError.preContext[0] = parseError.postContext[0] = (UChar)0; |
| |
| // TODO: Travis Keep: This won't always work. |
| UChar nineDigit = (UChar)(fZeroDigit + 9); |
| int32_t digitLen = fDigit.length(); |
| int32_t groupSepLen = fGroupingSeparator.length(); |
| int32_t decimalSepLen = fDecimalSeparator.length(); |
| |
| int32_t pos = 0; |
| int32_t patLen = pattern.length(); |
| // Part 0 is the positive pattern. Part 1, if present, is the negative |
| // pattern. |
| for (int32_t part=0; part<2 && pos<patLen; ++part) { |
| // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, |
| // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is |
| // between the prefix and suffix, and consists of pattern |
| // characters. In the prefix and suffix, percent, perMill, and |
| // currency symbols are recognized and translated. |
| int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0; |
| |
| // It's important that we don't change any fields of this object |
| // prematurely. We set the following variables for the multiplier, |
| // grouping, etc., and then only change the actual object fields if |
| // everything parses correctly. This also lets us register |
| // the data from part 0 and ignore the part 1, except for the |
| // prefix and suffix. |
| UnicodeString prefix; |
| UnicodeString suffix; |
| int32_t decimalPos = -1; |
| int32_t multiplier = 1; |
| int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sigDigitCount = 0; |
| int8_t groupingCount = -1; |
| int8_t groupingCount2 = -1; |
| int32_t padPos = -1; |
| UChar32 padChar = 0; |
| int32_t roundingPos = -1; |
| DigitList roundingInc; |
| int8_t expDigits = -1; |
| UBool expSignAlways = FALSE; |
| |
| // The affix is either the prefix or the suffix. |
| UnicodeString* affix = &prefix; |
| |
| int32_t start = pos; |
| UBool isPartDone = FALSE; |
| UChar32 ch; |
| |
| for (; !isPartDone && pos < patLen; ) { |
| // Todo: account for surrogate pairs |
| ch = pattern.char32At(pos); |
| switch (subpart) { |
| case 0: // Pattern proper subpart (between prefix & suffix) |
| // Process the digits, decimal, and grouping characters. We |
| // record five pieces of information. We expect the digits |
| // to occur in the pattern ####00.00####, and we record the |
| // number of left digits, zero (central) digits, and right |
| // digits. The position of the last grouping character is |
| // recorded (should be somewhere within the first two blocks |
| // of characters), as is the position of the decimal point, |
| // if any (should be in the zero digits). If there is no |
| // decimal point, then there should be no right digits. |
| if (pattern.compare(pos, digitLen, fDigit) == 0) { |
| if (zeroDigitCount > 0 || sigDigitCount > 0) { |
| ++digitRightCount; |
| } else { |
| ++digitLeftCount; |
| } |
| if (groupingCount >= 0 && decimalPos < 0) { |
| ++groupingCount; |
| } |
| pos += digitLen; |
| } else if ((ch >= fZeroDigit && ch <= nineDigit) || |
| ch == fSigDigit) { |
| if (digitRightCount > 0) { |
| // Unexpected '0' |
| debug("Unexpected '0'") |
| status = U_UNEXPECTED_TOKEN; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| if (ch == fSigDigit) { |
| ++sigDigitCount; |
| } else { |
| if (ch != fZeroDigit && roundingPos < 0) { |
| roundingPos = digitLeftCount + zeroDigitCount; |
| } |
| if (roundingPos >= 0) { |
| roundingInc.append((char)(ch - fZeroDigit + '0')); |
| } |
| ++zeroDigitCount; |
| } |
| if (groupingCount >= 0 && decimalPos < 0) { |
| ++groupingCount; |
| } |
| pos += U16_LENGTH(ch); |
| } else if (pattern.compare(pos, groupSepLen, fGroupingSeparator) == 0) { |
| if (decimalPos >= 0) { |
| // Grouping separator after decimal |
| debug("Grouping separator after decimal") |
| status = U_UNEXPECTED_TOKEN; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| groupingCount2 = groupingCount; |
| groupingCount = 0; |
| pos += groupSepLen; |
| } else if (pattern.compare(pos, decimalSepLen, fDecimalSeparator) == 0) { |
| if (decimalPos >= 0) { |
| // Multiple decimal separators |
| debug("Multiple decimal separators") |
| status = U_MULTIPLE_DECIMAL_SEPARATORS; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| // Intentionally incorporate the digitRightCount, |
| // even though it is illegal for this to be > 0 |
| // at this point. We check pattern syntax below. |
| decimalPos = digitLeftCount + zeroDigitCount + digitRightCount; |
| pos += decimalSepLen; |
| } else { |
| if (pattern.compare(pos, fExponent.length(), fExponent) == 0) { |
| if (expDigits >= 0) { |
| // Multiple exponential symbols |
| debug("Multiple exponential symbols") |
| status = U_MULTIPLE_EXPONENTIAL_SYMBOLS; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| if (groupingCount >= 0) { |
| // Grouping separator in exponential pattern |
| debug("Grouping separator in exponential pattern") |
| status = U_MALFORMED_EXPONENTIAL_PATTERN; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| pos += fExponent.length(); |
| // Check for positive prefix |
| if (pos < patLen |
| && pattern.compare(pos, fPlus.length(), fPlus) == 0) { |
| expSignAlways = TRUE; |
| pos += fPlus.length(); |
| } |
| // Use lookahead to parse out the exponential part of the |
| // pattern, then jump into suffix subpart. |
| expDigits = 0; |
| while (pos < patLen && |
| pattern.char32At(pos) == fZeroDigit) { |
| ++expDigits; |
| pos += U16_LENGTH(fZeroDigit); |
| } |
| |
| // 1. Require at least one mantissa pattern digit |
| // 2. Disallow "#+ @" in mantissa |
| // 3. Require at least one exponent pattern digit |
| if (((digitLeftCount + zeroDigitCount) < 1 && |
| (sigDigitCount + digitRightCount) < 1) || |
| (sigDigitCount > 0 && digitLeftCount > 0) || |
| expDigits < 1) { |
| // Malformed exponential pattern |
| debug("Malformed exponential pattern") |
| status = U_MALFORMED_EXPONENTIAL_PATTERN; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| } |
| // Transition to suffix subpart |
| subpart = 2; // suffix subpart |
| affix = &suffix; |
| sub0Limit = pos; |
| continue; |
| } |
| break; |
| case 1: // Prefix subpart |
| case 2: // Suffix subpart |
| // Process the prefix / suffix characters |
| // Process unquoted characters seen in prefix or suffix |
| // subpart. |
| |
| // Several syntax characters implicitly begins the |
| // next subpart if we are in the prefix; otherwise |
| // they are illegal if unquoted. |
| if (!pattern.compare(pos, digitLen, fDigit) || |
| !pattern.compare(pos, groupSepLen, fGroupingSeparator) || |
| !pattern.compare(pos, decimalSepLen, fDecimalSeparator) || |
| (ch >= fZeroDigit && ch <= nineDigit) || |
| ch == fSigDigit) { |
| if (subpart == 1) { // prefix subpart |
| subpart = 0; // pattern proper subpart |
| sub0Start = pos; // Reprocess this character |
| continue; |
| } else { |
| status = U_UNQUOTED_SPECIAL; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| } else if (ch == kCurrencySign) { |
| affix->append(kQuote); // Encode currency |
| // Use lookahead to determine if the currency sign is |
| // doubled or not. |
| U_ASSERT(U16_LENGTH(kCurrencySign) == 1); |
| if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrencySign) { |
| affix->append(kCurrencySign); |
| ++pos; // Skip over the doubled character |
| if ((pos+1) < pattern.length() && |
| pattern[pos+1] == kCurrencySign) { |
| affix->append(kCurrencySign); |
| ++pos; // Skip over the doubled character |
| out.fCurrencySignCount = fgCurrencySignCountInPluralFormat; |
| } else { |
| out.fCurrencySignCount = fgCurrencySignCountInISOFormat; |
| } |
| } else { |
| out.fCurrencySignCount = fgCurrencySignCountInSymbolFormat; |
| } |
| // Fall through to append(ch) |
| } else if (ch == kQuote) { |
| // A quote outside quotes indicates either the opening |
| // quote or two quotes, which is a quote literal. That is, |
| // we have the first quote in 'do' or o''clock. |
| U_ASSERT(U16_LENGTH(kQuote) == 1); |
| ++pos; |
| if (pos < pattern.length() && pattern[pos] == kQuote) { |
| affix->append(kQuote); // Encode quote |
| // Fall through to append(ch) |
| } else { |
| subpart += 2; // open quote |
| continue; |
| } |
| } else if (pattern.compare(pos, fSeparator.length(), fSeparator) == 0) { |
| // Don't allow separators in the prefix, and don't allow |
| // separators in the second pattern (part == 1). |
| if (subpart == 1 || part == 1) { |
| // Unexpected separator |
| debug("Unexpected separator") |
| status = U_UNEXPECTED_TOKEN; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| sub2Limit = pos; |
| isPartDone = TRUE; // Go to next part |
| pos += fSeparator.length(); |
| break; |
| } else if (pattern.compare(pos, fPercent.length(), fPercent) == 0) { |
| // Next handle characters which are appended directly. |
| if (multiplier != 1) { |
| // Too many percent/perMill characters |
| debug("Too many percent characters") |
| status = U_MULTIPLE_PERCENT_SYMBOLS; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| affix->append(kQuote); // Encode percent/perMill |
| affix->append(kPatternPercent); // Use unlocalized pattern char |
| multiplier = 100; |
| pos += fPercent.length(); |
| break; |
| } else if (pattern.compare(pos, fPerMill.length(), fPerMill) == 0) { |
| // Next handle characters which are appended directly. |
| if (multiplier != 1) { |
| // Too many percent/perMill characters |
| debug("Too many perMill characters") |
| status = U_MULTIPLE_PERMILL_SYMBOLS; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| affix->append(kQuote); // Encode percent/perMill |
| affix->append(kPatternPerMill); // Use unlocalized pattern char |
| multiplier = 1000; |
| pos += fPerMill.length(); |
| break; |
| } else if (pattern.compare(pos, fPadEscape.length(), fPadEscape) == 0) { |
| if (padPos >= 0 || // Multiple pad specifiers |
| (pos+1) == pattern.length()) { // Nothing after padEscape |
| debug("Multiple pad specifiers") |
| status = U_MULTIPLE_PAD_SPECIFIERS; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| padPos = pos; |
| pos += fPadEscape.length(); |
| padChar = pattern.char32At(pos); |
| pos += U16_LENGTH(padChar); |
| break; |
| } else if (pattern.compare(pos, fMinus.length(), fMinus) == 0) { |
| affix->append(kQuote); // Encode minus |
| affix->append(kPatternMinus); |
| pos += fMinus.length(); |
| break; |
| } else if (pattern.compare(pos, fPlus.length(), fPlus) == 0) { |
| affix->append(kQuote); // Encode plus |
| affix->append(kPatternPlus); |
| pos += fPlus.length(); |
| break; |
| } |
| // Unquoted, non-special characters fall through to here, as |
| // well as other code which needs to append something to the |
| // affix. |
| affix->append(ch); |
| pos += U16_LENGTH(ch); |
| break; |
| case 3: // Prefix subpart, in quote |
| case 4: // Suffix subpart, in quote |
| // A quote within quotes indicates either the closing |
| // quote or two quotes, which is a quote literal. That is, |
| // we have the second quote in 'do' or 'don''t'. |
| if (ch == kQuote) { |
| ++pos; |
| if (pos < pattern.length() && pattern[pos] == kQuote) { |
| affix->append(kQuote); // Encode quote |
| // Fall through to append(ch) |
| } else { |
| subpart -= 2; // close quote |
| continue; |
| } |
| } |
| affix->append(ch); |
| pos += U16_LENGTH(ch); |
| break; |
| } |
| } |
| |
| if (sub0Limit == 0) { |
| sub0Limit = pattern.length(); |
| } |
| |
| if (sub2Limit == 0) { |
| sub2Limit = pattern.length(); |
| } |
| |
| /* Handle patterns with no '0' pattern character. These patterns |
| * are legal, but must be recodified to make sense. "##.###" -> |
| * "#0.###". ".###" -> ".0##". |
| * |
| * We allow patterns of the form "####" to produce a zeroDigitCount |
| * of zero (got that?); although this seems like it might make it |
| * possible for format() to produce empty strings, format() checks |
| * for this condition and outputs a zero digit in this situation. |
| * Having a zeroDigitCount of zero yields a minimum integer digits |
| * of zero, which allows proper round-trip patterns. We don't want |
| * "#" to become "#0" when toPattern() is called (even though that's |
| * what it really is, semantically). |
| */ |
| if (zeroDigitCount == 0 && sigDigitCount == 0 && |
| digitLeftCount > 0 && decimalPos >= 0) { |
| // Handle "###.###" and "###." and ".###" |
| int n = decimalPos; |
| if (n == 0) |
| ++n; // Handle ".###" |
| digitRightCount = digitLeftCount - n; |
| digitLeftCount = n - 1; |
| zeroDigitCount = 1; |
| } |
| |
| // Do syntax checking on the digits, decimal points, and quotes. |
| if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) || |
| (decimalPos >= 0 && |
| (sigDigitCount > 0 || |
| decimalPos < digitLeftCount || |
| decimalPos > (digitLeftCount + zeroDigitCount))) || |
| groupingCount == 0 || groupingCount2 == 0 || |
| (sigDigitCount > 0 && zeroDigitCount > 0) || |
| subpart > 2) |
| { // subpart > 2 == unmatched quote |
| debug("Syntax error") |
| status = U_PATTERN_SYNTAX_ERROR; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| |
| // Make sure pad is at legal position before or after affix. |
| if (padPos >= 0) { |
| if (padPos == start) { |
| padPos = DecimalFormatPattern::kPadBeforePrefix; |
| } else if (padPos+2 == sub0Start) { |
| padPos = DecimalFormatPattern::kPadAfterPrefix; |
| } else if (padPos == sub0Limit) { |
| padPos = DecimalFormatPattern::kPadBeforeSuffix; |
| } else if (padPos+2 == sub2Limit) { |
| padPos = DecimalFormatPattern::kPadAfterSuffix; |
| } else { |
| // Illegal pad position |
| debug("Illegal pad position") |
| status = U_ILLEGAL_PAD_POSITION; |
| syntaxError(pattern,pos,parseError); |
| return; |
| } |
| } |
| |
| if (part == 0) { |
| out.fPosPatternsBogus = FALSE; |
| out.fPosPrefixPattern = prefix; |
| out.fPosSuffixPattern = suffix; |
| out.fNegPatternsBogus = TRUE; |
| out.fNegPrefixPattern.remove(); |
| out.fNegSuffixPattern.remove(); |
| |
| out.fUseExponentialNotation = (expDigits >= 0); |
| if (out.fUseExponentialNotation) { |
| out.fMinExponentDigits = expDigits; |
| } |
| out.fExponentSignAlwaysShown = expSignAlways; |
| int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRightCount; |
| // The effectiveDecimalPos is the position the decimal is at or |
| // would be at if there is no decimal. Note that if |
| // decimalPos<0, then digitTotalCount == digitLeftCount + |
| // zeroDigitCount. |
| int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTotalCount; |
| UBool isSigDig = (sigDigitCount > 0); |
| out.fUseSignificantDigits = isSigDig; |
| if (isSigDig) { |
| out.fMinimumSignificantDigits = sigDigitCount; |
| out.fMaximumSignificantDigits = sigDigitCount + digitRightCount; |
| } else { |
| int32_t minInt = effectiveDecimalPos - digitLeftCount; |
| out.fMinimumIntegerDigits = minInt; |
| out.fMaximumIntegerDigits = out.fUseExponentialNotation |
| ? digitLeftCount + out.fMinimumIntegerDigits |
| : gDefaultMaxIntegerDigits; |
| out.fMaximumFractionDigits = decimalPos >= 0 |
| ? (digitTotalCount - decimalPos) : 0; |
| out.fMinimumFractionDigits = decimalPos >= 0 |
| ? (digitLeftCount + zeroDigitCount - decimalPos) : 0; |
| } |
| out.fGroupingUsed = groupingCount > 0; |
| out.fGroupingSize = (groupingCount > 0) ? groupingCount : 0; |
| out.fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupingCount) |
| ? groupingCount2 : 0; |
| out.fMultiplier = multiplier; |
| out.fDecimalSeparatorAlwaysShown = decimalPos == 0 |
| || decimalPos == digitTotalCount; |
| if (padPos >= 0) { |
| out.fPadPosition = (DecimalFormatPattern::EPadPosition) padPos; |
| // To compute the format width, first set up sub0Limit - |
| // sub0Start. Add in prefix/suffix length later. |
| |
| // fFormatWidth = prefix.length() + suffix.length() + |
| // sub0Limit - sub0Start; |
| out.fFormatWidth = sub0Limit - sub0Start; |
| out.fPad = padChar; |
| } else { |
| out.fFormatWidth = 0; |
| } |
| if (roundingPos >= 0) { |
| out.fRoundingIncrementUsed = TRUE; |
| roundingInc.setDecimalAt(effectiveDecimalPos - roundingPos); |
| out.fRoundingIncrement = roundingInc; |
| } else { |
| out.fRoundingIncrementUsed = FALSE; |
| } |
| } else { |
| out.fNegPatternsBogus = FALSE; |
| out.fNegPrefixPattern = prefix; |
| out.fNegSuffixPattern = suffix; |
| } |
| } |
| |
| if (pattern.length() == 0) { |
| out.fNegPatternsBogus = TRUE; |
| out.fNegPrefixPattern.remove(); |
| out.fNegSuffixPattern.remove(); |
| out.fPosPatternsBogus = FALSE; |
| out.fPosPrefixPattern.remove(); |
| out.fPosSuffixPattern.remove(); |
| |
| out.fMinimumIntegerDigits = 0; |
| out.fMaximumIntegerDigits = kDoubleIntegerDigits; |
| out.fMinimumFractionDigits = 0; |
| out.fMaximumFractionDigits = kDoubleFractionDigits; |
| |
| out.fUseExponentialNotation = FALSE; |
| out.fCurrencySignCount = fgCurrencySignCountZero; |
| out.fGroupingUsed = FALSE; |
| out.fGroupingSize = 0; |
| out.fGroupingSize2 = 0; |
| out.fMultiplier = 1; |
| out.fDecimalSeparatorAlwaysShown = FALSE; |
| out.fFormatWidth = 0; |
| out.fRoundingIncrementUsed = FALSE; |
| } |
| |
| // If there was no negative pattern, or if the negative pattern is |
| // identical to the positive pattern, then prepend the minus sign to the |
| // positive pattern to form the negative pattern. |
| if (out.fNegPatternsBogus || |
| (out.fNegPrefixPattern == out.fPosPrefixPattern |
| && out.fNegSuffixPattern == out.fPosSuffixPattern)) { |
| out.fNegPatternsBogus = FALSE; |
| out.fNegSuffixPattern = out.fPosSuffixPattern; |
| out.fNegPrefixPattern.remove(); |
| out.fNegPrefixPattern.append(kQuote).append(kPatternMinus) |
| .append(out.fPosPrefixPattern); |
| } |
| // TODO: Deprecate/Remove out.fNegSuffixPattern and 3 other fields. |
| AffixPattern::parseAffixString( |
| out.fNegSuffixPattern, out.fNegSuffixAffix, status); |
| AffixPattern::parseAffixString( |
| out.fPosSuffixPattern, out.fPosSuffixAffix, status); |
| AffixPattern::parseAffixString( |
| out.fNegPrefixPattern, out.fNegPrefixAffix, status); |
| AffixPattern::parseAffixString( |
| out.fPosPrefixPattern, out.fPosPrefixAffix, status); |
| } |
| |
| U_NAMESPACE_END |
| |
| #endif /* !UCONFIG_NO_FORMATTING */ |