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