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