OLD | NEW |
(Empty) | |
| 1 /* |
| 2 ******************************************************************************* |
| 3 * Copyright (C) 1997-2014, International Business Machines Corporation and * |
| 4 * others. All Rights Reserved. * |
| 5 ******************************************************************************* |
| 6 */ |
| 7 |
| 8 #include "uassert.h" |
| 9 #include "decimalformatpattern.h" |
| 10 |
| 11 #if !UCONFIG_NO_FORMATTING |
| 12 |
| 13 #include "unicode/dcfmtsym.h" |
| 14 #include "unicode/format.h" |
| 15 #include "unicode/utf16.h" |
| 16 |
| 17 #ifdef FMT_DEBUG |
| 18 #define debug(x) printf("%s:%d: %s\n", __FILE__,__LINE__, x); |
| 19 #else |
| 20 #define debug(x) |
| 21 #endif |
| 22 |
| 23 #define kPatternZeroDigit ((UChar)0x0030) /*'0'*/ |
| 24 #define kPatternSignificantDigit ((UChar)0x0040) /*'@'*/ |
| 25 #define kPatternGroupingSeparator ((UChar)0x002C) /*','*/ |
| 26 #define kPatternDecimalSeparator ((UChar)0x002E) /*'.'*/ |
| 27 #define kPatternPerMill ((UChar)0x2030) |
| 28 #define kPatternPercent ((UChar)0x0025) /*'%'*/ |
| 29 #define kPatternDigit ((UChar)0x0023) /*'#'*/ |
| 30 #define kPatternSeparator ((UChar)0x003B) /*';'*/ |
| 31 #define kPatternExponent ((UChar)0x0045) /*'E'*/ |
| 32 #define kPatternPlus ((UChar)0x002B) /*'+'*/ |
| 33 #define kPatternMinus ((UChar)0x002D) /*'-'*/ |
| 34 #define kPatternPadEscape ((UChar)0x002A) /*'*'*/ |
| 35 #define kQuote ((UChar)0x0027) /*'\''*/ |
| 36 |
| 37 #define kCurrencySign ((UChar)0x00A4) |
| 38 #define kDefaultPad ((UChar)0x0020) /* */ |
| 39 |
| 40 U_NAMESPACE_BEGIN |
| 41 |
| 42 // TODO: Travis Keep: Copied from numfmt.cpp |
| 43 static int32_t kDoubleIntegerDigits = 309; |
| 44 static int32_t kDoubleFractionDigits = 340; |
| 45 |
| 46 |
| 47 // TODO: Travis Keep: Copied from numfmt.cpp |
| 48 static int32_t gDefaultMaxIntegerDigits = 2000000000; |
| 49 |
| 50 // TODO: Travis Keep: This function was copied from format.cpp |
| 51 static void syntaxError(const UnicodeString& pattern, |
| 52 int32_t pos, |
| 53 UParseError& parseError) { |
| 54 parseError.offset = pos; |
| 55 parseError.line=0; // we are not using line number |
| 56 |
| 57 // for pre-context |
| 58 int32_t start = (pos < U_PARSE_CONTEXT_LEN)? 0 : (pos - (U_PARSE_CONTEXT_LEN
-1 |
| 59 /* subtract 1 so th
at we have room for null*/)); |
| 60 int32_t stop = pos; |
| 61 pattern.extract(start,stop-start,parseError.preContext,0); |
| 62 //null terminate the buffer |
| 63 parseError.preContext[stop-start] = 0; |
| 64 |
| 65 //for post-context |
| 66 start = pos+1; |
| 67 stop = ((pos+U_PARSE_CONTEXT_LEN)<=pattern.length()) ? (pos+(U_PARSE_CONTEX
T_LEN-1)) : |
| 68 pattern.length(); |
| 69 pattern.extract(start,stop-start,parseError.postContext,0); |
| 70 //null terminate the buffer |
| 71 parseError.postContext[stop-start]= 0; |
| 72 } |
| 73 |
| 74 DecimalFormatPattern::DecimalFormatPattern() |
| 75 : fMinimumIntegerDigits(1), |
| 76 fMaximumIntegerDigits(gDefaultMaxIntegerDigits), |
| 77 fMinimumFractionDigits(0), |
| 78 fMaximumFractionDigits(3), |
| 79 fUseSignificantDigits(FALSE), |
| 80 fMinimumSignificantDigits(1), |
| 81 fMaximumSignificantDigits(6), |
| 82 fUseExponentialNotation(FALSE), |
| 83 fMinExponentDigits(0), |
| 84 fExponentSignAlwaysShown(FALSE), |
| 85 fCurrencySignCount(fgCurrencySignCountZero), |
| 86 fGroupingUsed(TRUE), |
| 87 fGroupingSize(0), |
| 88 fGroupingSize2(0), |
| 89 fMultiplier(1), |
| 90 fDecimalSeparatorAlwaysShown(FALSE), |
| 91 fFormatWidth(0), |
| 92 fRoundingIncrementUsed(FALSE), |
| 93 fRoundingIncrement(), |
| 94 fPad(kPatternPadEscape), |
| 95 fNegPatternsBogus(TRUE), |
| 96 fPosPatternsBogus(TRUE), |
| 97 fNegPrefixPattern(), |
| 98 fNegSuffixPattern(), |
| 99 fPosPrefixPattern(), |
| 100 fPosSuffixPattern(), |
| 101 fPadPosition(DecimalFormatPattern::kPadBeforePrefix) { |
| 102 } |
| 103 |
| 104 |
| 105 DecimalFormatPatternParser::DecimalFormatPatternParser() : |
| 106 fZeroDigit(kPatternZeroDigit), |
| 107 fSigDigit(kPatternSignificantDigit), |
| 108 fGroupingSeparator((UChar)kPatternGroupingSeparator), |
| 109 fDecimalSeparator((UChar)kPatternDecimalSeparator), |
| 110 fPercent((UChar)kPatternPercent), |
| 111 fPerMill((UChar)kPatternPerMill), |
| 112 fDigit((UChar)kPatternDigit), |
| 113 fSeparator((UChar)kPatternSeparator), |
| 114 fExponent((UChar)kPatternExponent), |
| 115 fPlus((UChar)kPatternPlus), |
| 116 fMinus((UChar)kPatternMinus), |
| 117 fPadEscape((UChar)kPatternPadEscape) { |
| 118 } |
| 119 |
| 120 void DecimalFormatPatternParser::useSymbols( |
| 121 const DecimalFormatSymbols& symbols) { |
| 122 fZeroDigit = symbols.getConstSymbol( |
| 123 DecimalFormatSymbols::kZeroDigitSymbol).char32At(0); |
| 124 fSigDigit = symbols.getConstSymbol( |
| 125 DecimalFormatSymbols::kSignificantDigitSymbol).char32At(0); |
| 126 fGroupingSeparator = symbols.getConstSymbol( |
| 127 DecimalFormatSymbols::kGroupingSeparatorSymbol); |
| 128 fDecimalSeparator = symbols.getConstSymbol( |
| 129 DecimalFormatSymbols::kDecimalSeparatorSymbol); |
| 130 fPercent = symbols.getConstSymbol( |
| 131 DecimalFormatSymbols::kPercentSymbol); |
| 132 fPerMill = symbols.getConstSymbol( |
| 133 DecimalFormatSymbols::kPerMillSymbol); |
| 134 fDigit = symbols.getConstSymbol( |
| 135 DecimalFormatSymbols::kDigitSymbol); |
| 136 fSeparator = symbols.getConstSymbol( |
| 137 DecimalFormatSymbols::kPatternSeparatorSymbol); |
| 138 fExponent = symbols.getConstSymbol( |
| 139 DecimalFormatSymbols::kExponentialSymbol); |
| 140 fPlus = symbols.getConstSymbol( |
| 141 DecimalFormatSymbols::kPlusSignSymbol); |
| 142 fMinus = symbols.getConstSymbol( |
| 143 DecimalFormatSymbols::kMinusSignSymbol); |
| 144 fPadEscape = symbols.getConstSymbol( |
| 145 DecimalFormatSymbols::kPadEscapeSymbol); |
| 146 } |
| 147 |
| 148 void |
| 149 DecimalFormatPatternParser::applyPatternWithoutExpandAffix( |
| 150 const UnicodeString& pattern, |
| 151 DecimalFormatPattern& out, |
| 152 UParseError& parseError, |
| 153 UErrorCode& status) { |
| 154 if (U_FAILURE(status)) |
| 155 { |
| 156 return; |
| 157 } |
| 158 out = DecimalFormatPattern(); |
| 159 |
| 160 // Clear error struct |
| 161 parseError.offset = -1; |
| 162 parseError.preContext[0] = parseError.postContext[0] = (UChar)0; |
| 163 |
| 164 // TODO: Travis Keep: This won't always work. |
| 165 UChar nineDigit = (UChar)(fZeroDigit + 9); |
| 166 int32_t digitLen = fDigit.length(); |
| 167 int32_t groupSepLen = fGroupingSeparator.length(); |
| 168 int32_t decimalSepLen = fDecimalSeparator.length(); |
| 169 |
| 170 int32_t pos = 0; |
| 171 int32_t patLen = pattern.length(); |
| 172 // Part 0 is the positive pattern. Part 1, if present, is the negative |
| 173 // pattern. |
| 174 for (int32_t part=0; part<2 && pos<patLen; ++part) { |
| 175 // The subpart ranges from 0 to 4: 0=pattern proper, 1=prefix, |
| 176 // 2=suffix, 3=prefix in quote, 4=suffix in quote. Subpart 0 is |
| 177 // between the prefix and suffix, and consists of pattern |
| 178 // characters. In the prefix and suffix, percent, perMill, and |
| 179 // currency symbols are recognized and translated. |
| 180 int32_t subpart = 1, sub0Start = 0, sub0Limit = 0, sub2Limit = 0; |
| 181 |
| 182 // It's important that we don't change any fields of this object |
| 183 // prematurely. We set the following variables for the multiplier, |
| 184 // grouping, etc., and then only change the actual object fields if |
| 185 // everything parses correctly. This also lets us register |
| 186 // the data from part 0 and ignore the part 1, except for the |
| 187 // prefix and suffix. |
| 188 UnicodeString prefix; |
| 189 UnicodeString suffix; |
| 190 int32_t decimalPos = -1; |
| 191 int32_t multiplier = 1; |
| 192 int32_t digitLeftCount = 0, zeroDigitCount = 0, digitRightCount = 0, sig
DigitCount = 0; |
| 193 int8_t groupingCount = -1; |
| 194 int8_t groupingCount2 = -1; |
| 195 int32_t padPos = -1; |
| 196 UChar32 padChar = 0; |
| 197 int32_t roundingPos = -1; |
| 198 DigitList roundingInc; |
| 199 int8_t expDigits = -1; |
| 200 UBool expSignAlways = FALSE; |
| 201 |
| 202 // The affix is either the prefix or the suffix. |
| 203 UnicodeString* affix = &prefix; |
| 204 |
| 205 int32_t start = pos; |
| 206 UBool isPartDone = FALSE; |
| 207 UChar32 ch; |
| 208 |
| 209 for (; !isPartDone && pos < patLen; ) { |
| 210 // Todo: account for surrogate pairs |
| 211 ch = pattern.char32At(pos); |
| 212 switch (subpart) { |
| 213 case 0: // Pattern proper subpart (between prefix & suffix) |
| 214 // Process the digits, decimal, and grouping characters. We |
| 215 // record five pieces of information. We expect the digits |
| 216 // to occur in the pattern ####00.00####, and we record the |
| 217 // number of left digits, zero (central) digits, and right |
| 218 // digits. The position of the last grouping character is |
| 219 // recorded (should be somewhere within the first two blocks |
| 220 // of characters), as is the position of the decimal point, |
| 221 // if any (should be in the zero digits). If there is no |
| 222 // decimal point, then there should be no right digits. |
| 223 if (pattern.compare(pos, digitLen, fDigit) == 0) { |
| 224 if (zeroDigitCount > 0 || sigDigitCount > 0) { |
| 225 ++digitRightCount; |
| 226 } else { |
| 227 ++digitLeftCount; |
| 228 } |
| 229 if (groupingCount >= 0 && decimalPos < 0) { |
| 230 ++groupingCount; |
| 231 } |
| 232 pos += digitLen; |
| 233 } else if ((ch >= fZeroDigit && ch <= nineDigit) || |
| 234 ch == fSigDigit) { |
| 235 if (digitRightCount > 0) { |
| 236 // Unexpected '0' |
| 237 debug("Unexpected '0'") |
| 238 status = U_UNEXPECTED_TOKEN; |
| 239 syntaxError(pattern,pos,parseError); |
| 240 return; |
| 241 } |
| 242 if (ch == fSigDigit) { |
| 243 ++sigDigitCount; |
| 244 } else { |
| 245 if (ch != fZeroDigit && roundingPos < 0) { |
| 246 roundingPos = digitLeftCount + zeroDigitCount; |
| 247 } |
| 248 if (roundingPos >= 0) { |
| 249 roundingInc.append((char)(ch - fZeroDigit + '0')); |
| 250 } |
| 251 ++zeroDigitCount; |
| 252 } |
| 253 if (groupingCount >= 0 && decimalPos < 0) { |
| 254 ++groupingCount; |
| 255 } |
| 256 pos += U16_LENGTH(ch); |
| 257 } else if (pattern.compare(pos, groupSepLen, fGroupingSeparator)
== 0) { |
| 258 if (decimalPos >= 0) { |
| 259 // Grouping separator after decimal |
| 260 debug("Grouping separator after decimal") |
| 261 status = U_UNEXPECTED_TOKEN; |
| 262 syntaxError(pattern,pos,parseError); |
| 263 return; |
| 264 } |
| 265 groupingCount2 = groupingCount; |
| 266 groupingCount = 0; |
| 267 pos += groupSepLen; |
| 268 } else if (pattern.compare(pos, decimalSepLen, fDecimalSeparator
) == 0) { |
| 269 if (decimalPos >= 0) { |
| 270 // Multiple decimal separators |
| 271 debug("Multiple decimal separators") |
| 272 status = U_MULTIPLE_DECIMAL_SEPARATORS; |
| 273 syntaxError(pattern,pos,parseError); |
| 274 return; |
| 275 } |
| 276 // Intentionally incorporate the digitRightCount, |
| 277 // even though it is illegal for this to be > 0 |
| 278 // at this point. We check pattern syntax below. |
| 279 decimalPos = digitLeftCount + zeroDigitCount + digitRightCou
nt; |
| 280 pos += decimalSepLen; |
| 281 } else { |
| 282 if (pattern.compare(pos, fExponent.length(), fExponent) == 0
) { |
| 283 if (expDigits >= 0) { |
| 284 // Multiple exponential symbols |
| 285 debug("Multiple exponential symbols") |
| 286 status = U_MULTIPLE_EXPONENTIAL_SYMBOLS; |
| 287 syntaxError(pattern,pos,parseError); |
| 288 return; |
| 289 } |
| 290 if (groupingCount >= 0) { |
| 291 // Grouping separator in exponential pattern |
| 292 debug("Grouping separator in exponential pattern") |
| 293 status = U_MALFORMED_EXPONENTIAL_PATTERN; |
| 294 syntaxError(pattern,pos,parseError); |
| 295 return; |
| 296 } |
| 297 pos += fExponent.length(); |
| 298 // Check for positive prefix |
| 299 if (pos < patLen |
| 300 && pattern.compare(pos, fPlus.length(), fPlus) == 0)
{ |
| 301 expSignAlways = TRUE; |
| 302 pos += fPlus.length(); |
| 303 } |
| 304 // Use lookahead to parse out the exponential part of th
e |
| 305 // pattern, then jump into suffix subpart. |
| 306 expDigits = 0; |
| 307 while (pos < patLen && |
| 308 pattern.char32At(pos) == fZeroDigit) { |
| 309 ++expDigits; |
| 310 pos += U16_LENGTH(fZeroDigit); |
| 311 } |
| 312 |
| 313 // 1. Require at least one mantissa pattern digit |
| 314 // 2. Disallow "#+ @" in mantissa |
| 315 // 3. Require at least one exponent pattern digit |
| 316 if (((digitLeftCount + zeroDigitCount) < 1 && |
| 317 (sigDigitCount + digitRightCount) < 1) || |
| 318 (sigDigitCount > 0 && digitLeftCount > 0) || |
| 319 expDigits < 1) { |
| 320 // Malformed exponential pattern |
| 321 debug("Malformed exponential pattern") |
| 322 status = U_MALFORMED_EXPONENTIAL_PATTERN; |
| 323 syntaxError(pattern,pos,parseError); |
| 324 return; |
| 325 } |
| 326 } |
| 327 // Transition to suffix subpart |
| 328 subpart = 2; // suffix subpart |
| 329 affix = &suffix; |
| 330 sub0Limit = pos; |
| 331 continue; |
| 332 } |
| 333 break; |
| 334 case 1: // Prefix subpart |
| 335 case 2: // Suffix subpart |
| 336 // Process the prefix / suffix characters |
| 337 // Process unquoted characters seen in prefix or suffix |
| 338 // subpart. |
| 339 |
| 340 // Several syntax characters implicitly begins the |
| 341 // next subpart if we are in the prefix; otherwise |
| 342 // they are illegal if unquoted. |
| 343 if (!pattern.compare(pos, digitLen, fDigit) || |
| 344 !pattern.compare(pos, groupSepLen, fGroupingSeparator) || |
| 345 !pattern.compare(pos, decimalSepLen, fDecimalSeparator) || |
| 346 (ch >= fZeroDigit && ch <= nineDigit) || |
| 347 ch == fSigDigit) { |
| 348 if (subpart == 1) { // prefix subpart |
| 349 subpart = 0; // pattern proper subpart |
| 350 sub0Start = pos; // Reprocess this character |
| 351 continue; |
| 352 } else { |
| 353 status = U_UNQUOTED_SPECIAL; |
| 354 syntaxError(pattern,pos,parseError); |
| 355 return; |
| 356 } |
| 357 } else if (ch == kCurrencySign) { |
| 358 affix->append(kQuote); // Encode currency |
| 359 // Use lookahead to determine if the currency sign is |
| 360 // doubled or not. |
| 361 U_ASSERT(U16_LENGTH(kCurrencySign) == 1); |
| 362 if ((pos+1) < pattern.length() && pattern[pos+1] == kCurrenc
ySign) { |
| 363 affix->append(kCurrencySign); |
| 364 ++pos; // Skip over the doubled character |
| 365 if ((pos+1) < pattern.length() && |
| 366 pattern[pos+1] == kCurrencySign) { |
| 367 affix->append(kCurrencySign); |
| 368 ++pos; // Skip over the doubled character |
| 369 out.fCurrencySignCount = fgCurrencySignCountInPlural
Format; |
| 370 } else { |
| 371 out.fCurrencySignCount = fgCurrencySignCountInISOFor
mat; |
| 372 } |
| 373 } else { |
| 374 out.fCurrencySignCount = fgCurrencySignCountInSymbolForm
at; |
| 375 } |
| 376 // Fall through to append(ch) |
| 377 } else if (ch == kQuote) { |
| 378 // A quote outside quotes indicates either the opening |
| 379 // quote or two quotes, which is a quote literal. That is, |
| 380 // we have the first quote in 'do' or o''clock. |
| 381 U_ASSERT(U16_LENGTH(kQuote) == 1); |
| 382 ++pos; |
| 383 if (pos < pattern.length() && pattern[pos] == kQuote) { |
| 384 affix->append(kQuote); // Encode quote |
| 385 // Fall through to append(ch) |
| 386 } else { |
| 387 subpart += 2; // open quote |
| 388 continue; |
| 389 } |
| 390 } else if (pattern.compare(pos, fSeparator.length(), fSeparator)
== 0) { |
| 391 // Don't allow separators in the prefix, and don't allow |
| 392 // separators in the second pattern (part == 1). |
| 393 if (subpart == 1 || part == 1) { |
| 394 // Unexpected separator |
| 395 debug("Unexpected separator") |
| 396 status = U_UNEXPECTED_TOKEN; |
| 397 syntaxError(pattern,pos,parseError); |
| 398 return; |
| 399 } |
| 400 sub2Limit = pos; |
| 401 isPartDone = TRUE; // Go to next part |
| 402 pos += fSeparator.length(); |
| 403 break; |
| 404 } else if (pattern.compare(pos, fPercent.length(), fPercent) ==
0) { |
| 405 // Next handle characters which are appended directly. |
| 406 if (multiplier != 1) { |
| 407 // Too many percent/perMill characters |
| 408 debug("Too many percent characters") |
| 409 status = U_MULTIPLE_PERCENT_SYMBOLS; |
| 410 syntaxError(pattern,pos,parseError); |
| 411 return; |
| 412 } |
| 413 affix->append(kQuote); // Encode percent/perMill |
| 414 affix->append(kPatternPercent); // Use unlocalized pattern c
har |
| 415 multiplier = 100; |
| 416 pos += fPercent.length(); |
| 417 break; |
| 418 } else if (pattern.compare(pos, fPerMill.length(), fPerMill) ==
0) { |
| 419 // Next handle characters which are appended directly. |
| 420 if (multiplier != 1) { |
| 421 // Too many percent/perMill characters |
| 422 debug("Too many perMill characters") |
| 423 status = U_MULTIPLE_PERMILL_SYMBOLS; |
| 424 syntaxError(pattern,pos,parseError); |
| 425 return; |
| 426 } |
| 427 affix->append(kQuote); // Encode percent/perMill |
| 428 affix->append(kPatternPerMill); // Use unlocalized pattern c
har |
| 429 multiplier = 1000; |
| 430 pos += fPerMill.length(); |
| 431 break; |
| 432 } else if (pattern.compare(pos, fPadEscape.length(), fPadEscape)
== 0) { |
| 433 if (padPos >= 0 || // Multiple pad specifiers |
| 434 (pos+1) == pattern.length()) { // Nothing after padEscap
e |
| 435 debug("Multiple pad specifiers") |
| 436 status = U_MULTIPLE_PAD_SPECIFIERS; |
| 437 syntaxError(pattern,pos,parseError); |
| 438 return; |
| 439 } |
| 440 padPos = pos; |
| 441 pos += fPadEscape.length(); |
| 442 padChar = pattern.char32At(pos); |
| 443 pos += U16_LENGTH(padChar); |
| 444 break; |
| 445 } else if (pattern.compare(pos, fMinus.length(), fMinus) == 0) { |
| 446 affix->append(kQuote); // Encode minus |
| 447 affix->append(kPatternMinus); |
| 448 pos += fMinus.length(); |
| 449 break; |
| 450 } else if (pattern.compare(pos, fPlus.length(), fPlus) == 0) { |
| 451 affix->append(kQuote); // Encode plus |
| 452 affix->append(kPatternPlus); |
| 453 pos += fPlus.length(); |
| 454 break; |
| 455 } |
| 456 // Unquoted, non-special characters fall through to here, as |
| 457 // well as other code which needs to append something to the |
| 458 // affix. |
| 459 affix->append(ch); |
| 460 pos += U16_LENGTH(ch); |
| 461 break; |
| 462 case 3: // Prefix subpart, in quote |
| 463 case 4: // Suffix subpart, in quote |
| 464 // A quote within quotes indicates either the closing |
| 465 // quote or two quotes, which is a quote literal. That is, |
| 466 // we have the second quote in 'do' or 'don''t'. |
| 467 if (ch == kQuote) { |
| 468 ++pos; |
| 469 if (pos < pattern.length() && pattern[pos] == kQuote) { |
| 470 affix->append(kQuote); // Encode quote |
| 471 // Fall through to append(ch) |
| 472 } else { |
| 473 subpart -= 2; // close quote |
| 474 continue; |
| 475 } |
| 476 } |
| 477 affix->append(ch); |
| 478 pos += U16_LENGTH(ch); |
| 479 break; |
| 480 } |
| 481 } |
| 482 |
| 483 if (sub0Limit == 0) { |
| 484 sub0Limit = pattern.length(); |
| 485 } |
| 486 |
| 487 if (sub2Limit == 0) { |
| 488 sub2Limit = pattern.length(); |
| 489 } |
| 490 |
| 491 /* Handle patterns with no '0' pattern character. These patterns |
| 492 * are legal, but must be recodified to make sense. "##.###" -> |
| 493 * "#0.###". ".###" -> ".0##". |
| 494 * |
| 495 * We allow patterns of the form "####" to produce a zeroDigitCount |
| 496 * of zero (got that?); although this seems like it might make it |
| 497 * possible for format() to produce empty strings, format() checks |
| 498 * for this condition and outputs a zero digit in this situation. |
| 499 * Having a zeroDigitCount of zero yields a minimum integer digits |
| 500 * of zero, which allows proper round-trip patterns. We don't want |
| 501 * "#" to become "#0" when toPattern() is called (even though that's |
| 502 * what it really is, semantically). |
| 503 */ |
| 504 if (zeroDigitCount == 0 && sigDigitCount == 0 && |
| 505 digitLeftCount > 0 && decimalPos >= 0) { |
| 506 // Handle "###.###" and "###." and ".###" |
| 507 int n = decimalPos; |
| 508 if (n == 0) |
| 509 ++n; // Handle ".###" |
| 510 digitRightCount = digitLeftCount - n; |
| 511 digitLeftCount = n - 1; |
| 512 zeroDigitCount = 1; |
| 513 } |
| 514 |
| 515 // Do syntax checking on the digits, decimal points, and quotes. |
| 516 if ((decimalPos < 0 && digitRightCount > 0 && sigDigitCount == 0) || |
| 517 (decimalPos >= 0 && |
| 518 (sigDigitCount > 0 || |
| 519 decimalPos < digitLeftCount || |
| 520 decimalPos > (digitLeftCount + zeroDigitCount))) || |
| 521 groupingCount == 0 || groupingCount2 == 0 || |
| 522 (sigDigitCount > 0 && zeroDigitCount > 0) || |
| 523 subpart > 2) |
| 524 { // subpart > 2 == unmatched quote |
| 525 debug("Syntax error") |
| 526 status = U_PATTERN_SYNTAX_ERROR; |
| 527 syntaxError(pattern,pos,parseError); |
| 528 return; |
| 529 } |
| 530 |
| 531 // Make sure pad is at legal position before or after affix. |
| 532 if (padPos >= 0) { |
| 533 if (padPos == start) { |
| 534 padPos = DecimalFormatPattern::kPadBeforePrefix; |
| 535 } else if (padPos+2 == sub0Start) { |
| 536 padPos = DecimalFormatPattern::kPadAfterPrefix; |
| 537 } else if (padPos == sub0Limit) { |
| 538 padPos = DecimalFormatPattern::kPadBeforeSuffix; |
| 539 } else if (padPos+2 == sub2Limit) { |
| 540 padPos = DecimalFormatPattern::kPadAfterSuffix; |
| 541 } else { |
| 542 // Illegal pad position |
| 543 debug("Illegal pad position") |
| 544 status = U_ILLEGAL_PAD_POSITION; |
| 545 syntaxError(pattern,pos,parseError); |
| 546 return; |
| 547 } |
| 548 } |
| 549 |
| 550 if (part == 0) { |
| 551 out.fPosPatternsBogus = FALSE; |
| 552 out.fPosPrefixPattern = prefix; |
| 553 out.fPosSuffixPattern = suffix; |
| 554 out.fNegPatternsBogus = TRUE; |
| 555 out.fNegPrefixPattern.remove(); |
| 556 out.fNegSuffixPattern.remove(); |
| 557 |
| 558 out.fUseExponentialNotation = (expDigits >= 0); |
| 559 if (out.fUseExponentialNotation) { |
| 560 out.fMinExponentDigits = expDigits; |
| 561 } |
| 562 out.fExponentSignAlwaysShown = expSignAlways; |
| 563 int32_t digitTotalCount = digitLeftCount + zeroDigitCount + digitRig
htCount; |
| 564 // The effectiveDecimalPos is the position the decimal is at or |
| 565 // would be at if there is no decimal. Note that if |
| 566 // decimalPos<0, then digitTotalCount == digitLeftCount + |
| 567 // zeroDigitCount. |
| 568 int32_t effectiveDecimalPos = decimalPos >= 0 ? decimalPos : digitTo
talCount; |
| 569 UBool isSigDig = (sigDigitCount > 0); |
| 570 out.fUseSignificantDigits = isSigDig; |
| 571 if (isSigDig) { |
| 572 out.fMinimumSignificantDigits = sigDigitCount; |
| 573 out.fMaximumSignificantDigits = sigDigitCount + digitRightCount; |
| 574 } else { |
| 575 int32_t minInt = effectiveDecimalPos - digitLeftCount; |
| 576 out.fMinimumIntegerDigits = minInt; |
| 577 out.fMaximumIntegerDigits = out.fUseExponentialNotation |
| 578 ? digitLeftCount + out.fMinimumIntegerDigits |
| 579 : gDefaultMaxIntegerDigits; |
| 580 out.fMaximumFractionDigits = decimalPos >= 0 |
| 581 ? (digitTotalCount - decimalPos) : 0; |
| 582 out.fMinimumFractionDigits = decimalPos >= 0 |
| 583 ? (digitLeftCount + zeroDigitCount - decimalPos) : 0; |
| 584 } |
| 585 out.fGroupingUsed = groupingCount > 0; |
| 586 out.fGroupingSize = (groupingCount > 0) ? groupingCount : 0; |
| 587 out.fGroupingSize2 = (groupingCount2 > 0 && groupingCount2 != groupi
ngCount) |
| 588 ? groupingCount2 : 0; |
| 589 out.fMultiplier = multiplier; |
| 590 out.fDecimalSeparatorAlwaysShown = decimalPos == 0 |
| 591 || decimalPos == digitTotalCount; |
| 592 if (padPos >= 0) { |
| 593 out.fPadPosition = (DecimalFormatPattern::EPadPosition) padPos; |
| 594 // To compute the format width, first set up sub0Limit - |
| 595 // sub0Start. Add in prefix/suffix length later. |
| 596 |
| 597 // fFormatWidth = prefix.length() + suffix.length() + |
| 598 // sub0Limit - sub0Start; |
| 599 out.fFormatWidth = sub0Limit - sub0Start; |
| 600 out.fPad = padChar; |
| 601 } else { |
| 602 out.fFormatWidth = 0; |
| 603 } |
| 604 if (roundingPos >= 0) { |
| 605 out.fRoundingIncrementUsed = TRUE; |
| 606 roundingInc.setDecimalAt(effectiveDecimalPos - roundingPos); |
| 607 out.fRoundingIncrement = roundingInc; |
| 608 } else { |
| 609 out.fRoundingIncrementUsed = FALSE; |
| 610 } |
| 611 } else { |
| 612 out.fNegPatternsBogus = FALSE; |
| 613 out.fNegPrefixPattern = prefix; |
| 614 out.fNegSuffixPattern = suffix; |
| 615 } |
| 616 } |
| 617 |
| 618 if (pattern.length() == 0) { |
| 619 out.fNegPatternsBogus = TRUE; |
| 620 out.fNegPrefixPattern.remove(); |
| 621 out.fNegSuffixPattern.remove(); |
| 622 out.fPosPatternsBogus = FALSE; |
| 623 out.fPosPrefixPattern.remove(); |
| 624 out.fPosSuffixPattern.remove(); |
| 625 |
| 626 out.fMinimumIntegerDigits = 0; |
| 627 out.fMaximumIntegerDigits = kDoubleIntegerDigits; |
| 628 out.fMinimumFractionDigits = 0; |
| 629 out.fMaximumFractionDigits = kDoubleFractionDigits; |
| 630 |
| 631 out.fUseExponentialNotation = FALSE; |
| 632 out.fCurrencySignCount = fgCurrencySignCountZero; |
| 633 out.fGroupingUsed = FALSE; |
| 634 out.fGroupingSize = 0; |
| 635 out.fGroupingSize2 = 0; |
| 636 out.fMultiplier = 1; |
| 637 out.fDecimalSeparatorAlwaysShown = FALSE; |
| 638 out.fFormatWidth = 0; |
| 639 out.fRoundingIncrementUsed = FALSE; |
| 640 } |
| 641 |
| 642 // If there was no negative pattern, or if the negative pattern is |
| 643 // identical to the positive pattern, then prepend the minus sign to the |
| 644 // positive pattern to form the negative pattern. |
| 645 if (out.fNegPatternsBogus || |
| 646 (out.fNegPrefixPattern == out.fPosPrefixPattern |
| 647 && out.fNegSuffixPattern == out.fPosSuffixPattern)) { |
| 648 out.fNegPatternsBogus = FALSE; |
| 649 out.fNegSuffixPattern = out.fPosSuffixPattern; |
| 650 out.fNegPrefixPattern.remove(); |
| 651 out.fNegPrefixPattern.append(kQuote).append(kPatternMinus) |
| 652 .append(out.fPosPrefixPattern); |
| 653 } |
| 654 } |
| 655 |
| 656 U_NAMESPACE_END |
| 657 |
| 658 #endif /* !UCONFIG_NO_FORMATTING */ |
OLD | NEW |