Index: source/i18n/decimalformatpattern.cpp |
diff --git a/source/i18n/decimalformatpattern.cpp b/source/i18n/decimalformatpattern.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a0ac40a25d1d42b615bb0f090432ff84e4165897 |
--- /dev/null |
+++ b/source/i18n/decimalformatpattern.cpp |
@@ -0,0 +1,658 @@ |
+/* |
+******************************************************************************* |
+* Copyright (C) 1997-2014, International Business Machines Corporation and * |
+* others. All Rights Reserved. * |
+******************************************************************************* |
+*/ |
+ |
+#include "uassert.h" |
+#include "decimalformatpattern.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
+#include "unicode/dcfmtsym.h" |
+#include "unicode/format.h" |
+#include "unicode/utf16.h" |
+ |
+#ifdef FMT_DEBUG |
+#define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); |
+#else |
+#define debug(x) |
+#endif |
+ |
+#define kPatternZeroDigit ((UChar)0x0030) /*'0'*/ |
+#define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/ |
+#define kPatternGroupingSeparator ((UChar)0x002C) /*','*/ |
+#define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/ |
+#define kPatternPerMill ((UChar)0x2030) |
+#define kPatternPercent ((UChar)0x0025) /*'%'*/ |
+#define kPatternDigit ((UChar)0x0023) /*'#'*/ |
+#define kPatternSeparator ((UChar)0x003B) /*';'*/ |
+#define kPatternExponent ((UChar)0x0045) /*'E'*/ |
+#define kPatternPlus ((UChar)0x002B) /*'+'*/ |
+#define kPatternMinus ((UChar)0x002D) /*'-'*/ |
+#define kPatternPadEscape ((UChar)0x002A) /*'*'*/ |
+#define kQuote ((UChar)0x0027) /*'\''*/ |
+ |
+#define kCurrencySign ((UChar)0x00A4) |
+#define kDefaultPad ((UChar)0x0020) /* */ |
+ |
+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(kPatternPadEscape), |
+ 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); |
+ } |
+} |
+ |
+U_NAMESPACE_END |
+ |
+#endif /* !UCONFIG_NO_FORMATTING */ |