]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/decimalformatpattern.cpp
ICU-531.48.tar.gz
[apple/icu.git] / icuSources / i18n / decimalformatpattern.cpp
CommitLineData
57a6839d
A
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
40U_NAMESPACE_BEGIN
41
42// TODO: Travis Keep: Copied from numfmt.cpp
43static int32_t kDoubleIntegerDigits = 309;
44static int32_t kDoubleFractionDigits = 340;
45
46
47// TODO: Travis Keep: Copied from numfmt.cpp
48static int32_t gDefaultMaxIntegerDigits = 2000000000;
49
50// TODO: Travis Keep: This function was copied from format.cpp
51static 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 that 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_CONTEXT_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
74DecimalFormatPattern::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
105DecimalFormatPatternParser::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
120void 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
148void
149DecimalFormatPatternParser::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, sigDigitCount = 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 + digitRightCount;
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 the
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] == kCurrencySign) {
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 = fgCurrencySignCountInPluralFormat;
370 } else {
371 out.fCurrencySignCount = fgCurrencySignCountInISOFormat;
372 }
373 } else {
374 out.fCurrencySignCount = fgCurrencySignCountInSymbolFormat;
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 char
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 char
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 padEscape
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 + digitRightCount;
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 : digitTotalCount;
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 != groupingCount)
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(); // restore this line
651 out.fNegPrefixPattern.append(kQuote).append(kPatternMinus)
652 .append(out.fPosPrefixPattern);
653 }
654}
655
656U_NAMESPACE_END
657
658#endif /* !UCONFIG_NO_FORMATTING */