/*
 * Copyright (C) 2015, International Business Machines
 * Corporation and others.  All Rights Reserved.
 *
 * file name: decimfmtimpl.cpp
 */

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING
#include "starboard/client_porting/poem/string_poem.h"
#if !defined(STARBOARD)
#include <math.h>
#endif
#include "unicode/numfmt.h"
#include "unicode/plurrule.h"
#include "unicode/ustring.h"
#include "decimalformatpattern.h"
#include "decimalformatpatternimpl.h"
#include "decimfmtimpl.h"
#include "fphdlimp.h"
#include "plurrule_impl.h"
#include "valueformatter.h"
#include "visibledigits.h"

U_NAMESPACE_BEGIN

static const int32_t kMaxScientificIntegerDigits = 8;

static const int32_t kFormattingPosPrefix = (1 << 0);
static const int32_t kFormattingNegPrefix = (1 << 1);
static const int32_t kFormattingPosSuffix = (1 << 2);
static const int32_t kFormattingNegSuffix = (1 << 3);
static const int32_t kFormattingSymbols = (1 << 4);
static const int32_t kFormattingCurrency = (1 << 5);
static const int32_t kFormattingUsesCurrency = (1 << 6);
static const int32_t kFormattingPluralRules = (1 << 7);
static const int32_t kFormattingAffixParser = (1 << 8);
static const int32_t kFormattingCurrencyAffixInfo = (1 << 9);
static const int32_t kFormattingAll = (1 << 10) - 1;
static const int32_t kFormattingAffixes =
        kFormattingPosPrefix | kFormattingPosSuffix |
        kFormattingNegPrefix | kFormattingNegSuffix;
static const int32_t kFormattingAffixParserWithCurrency =
        kFormattingAffixParser | kFormattingCurrencyAffixInfo;

DecimalFormatImpl::DecimalFormatImpl(
        NumberFormat *super,
        const Locale &locale,
        const UnicodeString &pattern,
        UErrorCode &status)
        : fSuper(super),
          fScale(0),
          fRoundingMode(DecimalFormat::kRoundHalfEven),
          fSymbols(NULL),
          fCurrencyUsage(UCURR_USAGE_STANDARD),
          fRules(NULL),
          fMonetary(FALSE) {
    if (U_FAILURE(status)) {
        return;
    }
    fSymbols = new DecimalFormatSymbols(
            locale, status);
    if (fSymbols == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    UParseError parseError;
    applyPattern(pattern, FALSE, parseError, status);
    updateAll(status);
}

DecimalFormatImpl::DecimalFormatImpl(
        NumberFormat *super,
        const UnicodeString &pattern,
        DecimalFormatSymbols *symbolsToAdopt,
        UParseError &parseError,
        UErrorCode &status)
        : fSuper(super),
          fScale(0),
          fRoundingMode(DecimalFormat::kRoundHalfEven),
          fSymbols(symbolsToAdopt),
          fCurrencyUsage(UCURR_USAGE_STANDARD),
          fRules(NULL),
          fMonetary(FALSE) {
    applyPattern(pattern, FALSE, parseError, status);
    updateAll(status);
}

DecimalFormatImpl::DecimalFormatImpl(
    NumberFormat *super, const DecimalFormatImpl &other, UErrorCode &status) :
          fSuper(super),
          fMultiplier(other.fMultiplier),
          fScale(other.fScale),
          fRoundingMode(other.fRoundingMode),
          fMinSigDigits(other.fMinSigDigits),
          fMaxSigDigits(other.fMaxSigDigits),
          fUseScientific(other.fUseScientific),
          fUseSigDigits(other.fUseSigDigits),
          fGrouping(other.fGrouping),
          fPositivePrefixPattern(other.fPositivePrefixPattern),
          fNegativePrefixPattern(other.fNegativePrefixPattern),
          fPositiveSuffixPattern(other.fPositiveSuffixPattern),
          fNegativeSuffixPattern(other.fNegativeSuffixPattern),
          fSymbols(other.fSymbols),
          fCurrencyUsage(other.fCurrencyUsage),
          fRules(NULL),
          fMonetary(other.fMonetary),
          fAffixParser(other.fAffixParser),
          fCurrencyAffixInfo(other.fCurrencyAffixInfo),
          fEffPrecision(other.fEffPrecision),
          fEffGrouping(other.fEffGrouping),
          fOptions(other.fOptions),
          fFormatter(other.fFormatter),
          fAffixes(other.fAffixes) {
    fSymbols = new DecimalFormatSymbols(*fSymbols);
    if (fSymbols == NULL && U_SUCCESS(status)) {
        status = U_MEMORY_ALLOCATION_ERROR;
    }
    if (other.fRules != NULL) {
        fRules = new PluralRules(*other.fRules);
        if (fRules == NULL && U_SUCCESS(status)) {
            status = U_MEMORY_ALLOCATION_ERROR;
        }
    }
}


DecimalFormatImpl &
DecimalFormatImpl::assign(const DecimalFormatImpl &other, UErrorCode &status) {
    if (U_FAILURE(status) || this == &other) {
        return (*this);
    }
    UObject::operator=(other);
    fMultiplier = other.fMultiplier;
    fScale = other.fScale;
    fRoundingMode = other.fRoundingMode;
    fMinSigDigits = other.fMinSigDigits;
    fMaxSigDigits = other.fMaxSigDigits;
    fUseScientific = other.fUseScientific;
    fUseSigDigits = other.fUseSigDigits;
    fGrouping = other.fGrouping;
    fPositivePrefixPattern = other.fPositivePrefixPattern;
    fNegativePrefixPattern = other.fNegativePrefixPattern;
    fPositiveSuffixPattern = other.fPositiveSuffixPattern;
    fNegativeSuffixPattern = other.fNegativeSuffixPattern;
    fCurrencyUsage = other.fCurrencyUsage;
    fMonetary = other.fMonetary;
    fAffixParser = other.fAffixParser;
    fCurrencyAffixInfo = other.fCurrencyAffixInfo;
    fEffPrecision = other.fEffPrecision;
    fEffGrouping = other.fEffGrouping;
    fOptions = other.fOptions;
    fFormatter = other.fFormatter;
    fAffixes = other.fAffixes;
    *fSymbols = *other.fSymbols;
    if (fRules != NULL && other.fRules != NULL) {
        *fRules = *other.fRules;
    } else {
        delete fRules;
        fRules = other.fRules;
        if (fRules != NULL) {
            fRules = new PluralRules(*fRules);
            if (fRules == NULL) {
                status = U_MEMORY_ALLOCATION_ERROR;
                return *this;
            }
        }
    }
    return *this;
}

UBool
DecimalFormatImpl::operator==(const DecimalFormatImpl &other) const {
    if (this == &other) {
        return TRUE;
    }
    return (fMultiplier == other.fMultiplier)
            && (fScale == other.fScale)
            && (fRoundingMode == other.fRoundingMode)
            && (fMinSigDigits == other.fMinSigDigits)
            && (fMaxSigDigits == other.fMaxSigDigits)
            && (fUseScientific == other.fUseScientific)
            && (fUseSigDigits == other.fUseSigDigits)
            && fGrouping.equals(other.fGrouping)
            && fPositivePrefixPattern.equals(other.fPositivePrefixPattern)
            && fNegativePrefixPattern.equals(other.fNegativePrefixPattern)
            && fPositiveSuffixPattern.equals(other.fPositiveSuffixPattern)
            && fNegativeSuffixPattern.equals(other.fNegativeSuffixPattern)
            && fCurrencyUsage == other.fCurrencyUsage
            && fAffixParser.equals(other.fAffixParser)
            && fCurrencyAffixInfo.equals(other.fCurrencyAffixInfo)
            && fEffPrecision.equals(other.fEffPrecision)
            && fEffGrouping.equals(other.fEffGrouping)
            && fOptions.equals(other.fOptions)
            && fFormatter.equals(other.fFormatter)
            && fAffixes.equals(other.fAffixes)
            && (*fSymbols == *other.fSymbols)
            && ((fRules == other.fRules) || (
                    (fRules != NULL) && (other.fRules != NULL)
                    && (*fRules == *other.fRules)))
            && (fMonetary == other.fMonetary);
}

DecimalFormatImpl::~DecimalFormatImpl() {
    delete fSymbols;
    delete fRules;
}

ValueFormatter &
DecimalFormatImpl::prepareValueFormatter(ValueFormatter &vf) const {
    if (fUseScientific) {
        vf.prepareScientificFormatting(
                fFormatter, fEffPrecision, fOptions);
        return vf;
    }
    vf.prepareFixedDecimalFormatting(
            fFormatter, fEffGrouping, fEffPrecision.fMantissa, fOptions.fMantissa);
    return vf;
}

int32_t
DecimalFormatImpl::getPatternScale() const {
    UBool usesPercent = fPositivePrefixPattern.usesPercent() || 
            fPositiveSuffixPattern.usesPercent() || 
            fNegativePrefixPattern.usesPercent() || 
            fNegativeSuffixPattern.usesPercent();
    if (usesPercent) {
        return 2;
    }
    UBool usesPermill = fPositivePrefixPattern.usesPermill() || 
            fPositiveSuffixPattern.usesPermill() || 
            fNegativePrefixPattern.usesPermill() || 
            fNegativeSuffixPattern.usesPermill();
    if (usesPermill) {
        return 3;
    }
    return 0;
}
    
void
DecimalFormatImpl::setMultiplierScale(int32_t scale) {
    if (scale == 0) {
        // Needed to preserve equality. fMultiplier == 0 means
        // multiplier is 1.
        fMultiplier.set(0);
    } else {
        fMultiplier.set(1);
        fMultiplier.shiftDecimalRight(scale);
    }
}

UnicodeString &
DecimalFormatImpl::format(
        int32_t number,
        UnicodeString &appendTo,
        FieldPosition &pos,
        UErrorCode &status) const {
    FieldPositionOnlyHandler handler(pos);
    return formatInt32(number, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        int32_t number,
        UnicodeString &appendTo,
        FieldPositionIterator *posIter,
        UErrorCode &status) const {
    FieldPositionIteratorHandler handler(posIter, status);
    return formatInt32(number, appendTo, handler, status);
}

template<class T>
UBool DecimalFormatImpl::maybeFormatWithDigitList(
        T number,
        UnicodeString &appendTo,
        FieldPositionHandler &handler,
        UErrorCode &status) const {
    if (!fMultiplier.isZero()) {
        DigitList digits;
        digits.set(number);
        digits.mult(fMultiplier, status);
        digits.shiftDecimalRight(fScale);
        formatAdjustedDigitList(digits, appendTo, handler, status);
        return TRUE;
    }
    if (fScale != 0) {
        DigitList digits;
        digits.set(number);
        digits.shiftDecimalRight(fScale);
        formatAdjustedDigitList(digits, appendTo, handler, status);
        return TRUE;
    }
    return FALSE;
}

template<class T>
UBool DecimalFormatImpl::maybeInitVisibleDigitsFromDigitList(
        T number,
        VisibleDigitsWithExponent &visibleDigits,
        UErrorCode &status) const {
    if (!fMultiplier.isZero()) {
        DigitList digits;
        digits.set(number);
        digits.mult(fMultiplier, status);
        digits.shiftDecimalRight(fScale);
        initVisibleDigitsFromAdjusted(digits, visibleDigits, status);
        return TRUE;
    }
    if (fScale != 0) {
        DigitList digits;
        digits.set(number);
        digits.shiftDecimalRight(fScale);
        initVisibleDigitsFromAdjusted(digits, visibleDigits, status);
        return TRUE;
    }
    return FALSE;
}

UnicodeString &
DecimalFormatImpl::formatInt32(
        int32_t number,
        UnicodeString &appendTo,
        FieldPositionHandler &handler,
        UErrorCode &status) const {
    if (maybeFormatWithDigitList(number, appendTo, handler, status)) {
        return appendTo;
    }
    ValueFormatter vf;
    return fAffixes.formatInt32(
            number,
            prepareValueFormatter(vf),
            handler,
            fRules,
            appendTo,
            status);
}

UnicodeString &
DecimalFormatImpl::formatInt64(
        int64_t number,
        UnicodeString &appendTo,
        FieldPositionHandler &handler,
        UErrorCode &status) const {
    if (number >= INT32_MIN && number <= INT32_MAX) {
        return formatInt32((int32_t) number, appendTo, handler, status);
    }
    VisibleDigitsWithExponent digits;
    initVisibleDigitsWithExponent(number, digits, status);
    return formatVisibleDigitsWithExponent(
            digits, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::formatDouble(
        double number,
        UnicodeString &appendTo,
        FieldPositionHandler &handler,
        UErrorCode &status) const {
    VisibleDigitsWithExponent digits;
    initVisibleDigitsWithExponent(number, digits, status);
    return formatVisibleDigitsWithExponent(
            digits, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        double number,
        UnicodeString &appendTo,
        FieldPosition &pos,
        UErrorCode &status) const {
    FieldPositionOnlyHandler handler(pos);
    return formatDouble(number, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        const DigitList &number,
        UnicodeString &appendTo,
        FieldPosition &pos,
        UErrorCode &status) const {
    DigitList dl(number);
    FieldPositionOnlyHandler handler(pos);
    return formatDigitList(dl, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        int64_t number,
        UnicodeString &appendTo,
        FieldPosition &pos,
        UErrorCode &status) const {
    FieldPositionOnlyHandler handler(pos);
    return formatInt64(number, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        int64_t number,
        UnicodeString &appendTo,
        FieldPositionIterator *posIter,
        UErrorCode &status) const {
    FieldPositionIteratorHandler handler(posIter, status);
    return formatInt64(number, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        double number,
        UnicodeString &appendTo,
        FieldPositionIterator *posIter,
        UErrorCode &status) const {
    FieldPositionIteratorHandler handler(posIter, status);
    return formatDouble(number, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        const DigitList &number,
        UnicodeString &appendTo,
        FieldPositionIterator *posIter,
        UErrorCode &status) const {
    DigitList dl(number);
    FieldPositionIteratorHandler handler(posIter, status);
    return formatDigitList(dl, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        const StringPiece &number,
        UnicodeString &appendTo,
        FieldPositionIterator *posIter,
        UErrorCode &status) const {
    DigitList dl;
    dl.set(number, status);
    FieldPositionIteratorHandler handler(posIter, status);
    return formatDigitList(dl, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        const VisibleDigitsWithExponent &digits,
        UnicodeString &appendTo,
        FieldPosition &pos,
        UErrorCode &status) const {
    FieldPositionOnlyHandler handler(pos);
    return formatVisibleDigitsWithExponent(
            digits, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::format(
        const VisibleDigitsWithExponent &digits,
        UnicodeString &appendTo,
        FieldPositionIterator *posIter,
        UErrorCode &status) const {
    FieldPositionIteratorHandler handler(posIter, status);
    return formatVisibleDigitsWithExponent(
            digits, appendTo, handler, status);
}

DigitList &
DecimalFormatImpl::adjustDigitList(
        DigitList &number, UErrorCode &status) const {
    number.setRoundingMode(fRoundingMode);
    if (!fMultiplier.isZero()) {
        number.mult(fMultiplier, status);
    }
    if (fScale != 0) {
        number.shiftDecimalRight(fScale);
    }
    number.reduce();
    return number;
}

UnicodeString &
DecimalFormatImpl::formatDigitList(
        DigitList &number,
        UnicodeString &appendTo,
        FieldPositionHandler &handler,
        UErrorCode &status) const {
    VisibleDigitsWithExponent digits;
    initVisibleDigitsWithExponent(number, digits, status);
    return formatVisibleDigitsWithExponent(
            digits, appendTo, handler, status);
}

UnicodeString &
DecimalFormatImpl::formatAdjustedDigitList(
        DigitList &number,
        UnicodeString &appendTo,
        FieldPositionHandler &handler,
        UErrorCode &status) const {
    ValueFormatter vf;
    return fAffixes.format(
            number,
            prepareValueFormatter(vf),
            handler,
            fRules,
            appendTo,
            status);
}

UnicodeString &
DecimalFormatImpl::formatVisibleDigitsWithExponent(
        const VisibleDigitsWithExponent &digits,
        UnicodeString &appendTo,
        FieldPositionHandler &handler,
        UErrorCode &status) const {
    ValueFormatter vf;
    return fAffixes.format(
            digits,
            prepareValueFormatter(vf),
            handler,
            fRules,
            appendTo,
            status);
}

static FixedDecimal &initFixedDecimal(
        const VisibleDigits &digits, FixedDecimal &result) {
    result.source = 0.0;
    result.isNegative = digits.isNegative();
    result.isNanOrInfinity = digits.isNaNOrInfinity();
    digits.getFixedDecimal(
            result.source, result.intValue, result.decimalDigits,
            result.decimalDigitsWithoutTrailingZeros,
            result.visibleDecimalDigitCount, result.hasIntegerValue);
    return result;
}

FixedDecimal &
DecimalFormatImpl::getFixedDecimal(double number, FixedDecimal &result, UErrorCode &status) const {
    if (U_FAILURE(status)) {
        return result;
    }
    VisibleDigits digits;
    fEffPrecision.fMantissa.initVisibleDigits(number, digits, status);
    return initFixedDecimal(digits, result);
}

FixedDecimal &
DecimalFormatImpl::getFixedDecimal(
        DigitList &number, FixedDecimal &result, UErrorCode &status) const {
    if (U_FAILURE(status)) {
        return result;
    }
    VisibleDigits digits;
    fEffPrecision.fMantissa.initVisibleDigits(number, digits, status);
    return initFixedDecimal(digits, result);
}

VisibleDigitsWithExponent &
DecimalFormatImpl::initVisibleDigitsWithExponent(
        int64_t number,
        VisibleDigitsWithExponent &digits,
        UErrorCode &status) const {
    if (maybeInitVisibleDigitsFromDigitList(
            number, digits, status)) {
        return digits;
    }
    if (fUseScientific) {
        fEffPrecision.initVisibleDigitsWithExponent(
                number, digits, status);
    } else {
        fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
                number, digits, status);
    }
    return digits;
}

VisibleDigitsWithExponent &
DecimalFormatImpl::initVisibleDigitsWithExponent(
        double number,
        VisibleDigitsWithExponent &digits,
        UErrorCode &status) const {
    if (maybeInitVisibleDigitsFromDigitList(
            number, digits, status)) {
        return digits;
    }
    if (fUseScientific) {
        fEffPrecision.initVisibleDigitsWithExponent(
                number, digits, status);
    } else {
        fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
                number, digits, status);
    }
    return digits;
}

VisibleDigitsWithExponent &
DecimalFormatImpl::initVisibleDigitsWithExponent(
        DigitList &number,
        VisibleDigitsWithExponent &digits,
        UErrorCode &status) const {
    adjustDigitList(number, status);
    return initVisibleDigitsFromAdjusted(number, digits, status);
}

VisibleDigitsWithExponent &
DecimalFormatImpl::initVisibleDigitsFromAdjusted(
        DigitList &number,
        VisibleDigitsWithExponent &digits,
        UErrorCode &status) const {
    if (fUseScientific) {
        fEffPrecision.initVisibleDigitsWithExponent(
                number, digits, status);
    } else {
        fEffPrecision.fMantissa.initVisibleDigitsWithExponent(
                number, digits, status);
    }
    return digits;
}

DigitList &
DecimalFormatImpl::round(
        DigitList &number, UErrorCode &status) const {
    if (number.isNaN() || number.isInfinite()) {
        return number;
    }
    adjustDigitList(number, status);
    ValueFormatter vf;
    prepareValueFormatter(vf);
    return vf.round(number, status);
}

void
DecimalFormatImpl::setMinimumSignificantDigits(int32_t newValue) {
    fMinSigDigits = newValue;
    fUseSigDigits = TRUE; // ticket 9936
    updatePrecision();
}
        
void
DecimalFormatImpl::setMaximumSignificantDigits(int32_t newValue) {
    fMaxSigDigits = newValue;
    fUseSigDigits = TRUE; // ticket 9936
    updatePrecision();
}

void
DecimalFormatImpl::setMinMaxSignificantDigits(int32_t min, int32_t max) {
    fMinSigDigits = min;
    fMaxSigDigits = max;
    fUseSigDigits = TRUE; // ticket 9936
    updatePrecision();
}

void
DecimalFormatImpl::setScientificNotation(UBool newValue) {
    fUseScientific = newValue;
    updatePrecision();
}
        
void
DecimalFormatImpl::setSignificantDigitsUsed(UBool newValue) {
    fUseSigDigits = newValue;
    updatePrecision();
}
        
void
DecimalFormatImpl::setGroupingSize(int32_t newValue) {
    fGrouping.fGrouping = newValue;
    updateGrouping();
}

void
DecimalFormatImpl::setSecondaryGroupingSize(int32_t newValue) {
    fGrouping.fGrouping2 = newValue;
    updateGrouping();
}

void
DecimalFormatImpl::setMinimumGroupingDigits(int32_t newValue) {
    fGrouping.fMinGrouping = newValue;
    updateGrouping();
}

void
DecimalFormatImpl::setCurrencyUsage(
        UCurrencyUsage currencyUsage, UErrorCode &status) {
    fCurrencyUsage = currencyUsage;
    updateFormatting(kFormattingCurrency, status);
}

void
DecimalFormatImpl::setRoundingIncrement(double d) {
    if (d > 0.0) {
        fEffPrecision.fMantissa.fRoundingIncrement.set(d);
    } else {
        fEffPrecision.fMantissa.fRoundingIncrement.set(0.0);
    }
}

double
DecimalFormatImpl::getRoundingIncrement() const {
    return fEffPrecision.fMantissa.fRoundingIncrement.getDouble();
}

int32_t
DecimalFormatImpl::getMultiplier() const {
    if (fMultiplier.isZero()) {
        return 1;
    }
    return (int32_t) fMultiplier.getDouble();
}

void
DecimalFormatImpl::setMultiplier(int32_t m) {
    if (m == 0 || m == 1) {
        fMultiplier.set(0);
    } else {
        fMultiplier.set(m);
    }
}

void
DecimalFormatImpl::setPositivePrefix(const UnicodeString &str) {
    fPositivePrefixPattern.remove();
    fPositivePrefixPattern.addLiteral(str.getBuffer(), 0, str.length());
    UErrorCode status = U_ZERO_ERROR;
    updateFormatting(kFormattingPosPrefix, status);
}

void
DecimalFormatImpl::setPositiveSuffix(const UnicodeString &str) {
    fPositiveSuffixPattern.remove();
    fPositiveSuffixPattern.addLiteral(str.getBuffer(), 0, str.length());
    UErrorCode status = U_ZERO_ERROR;
    updateFormatting(kFormattingPosSuffix, status);
}

void
DecimalFormatImpl::setNegativePrefix(const UnicodeString &str) {
    fNegativePrefixPattern.remove();
    fNegativePrefixPattern.addLiteral(str.getBuffer(), 0, str.length());
    UErrorCode status = U_ZERO_ERROR;
    updateFormatting(kFormattingNegPrefix, status);
}

void
DecimalFormatImpl::setNegativeSuffix(const UnicodeString &str) {
    fNegativeSuffixPattern.remove();
    fNegativeSuffixPattern.addLiteral(str.getBuffer(), 0, str.length());
    UErrorCode status = U_ZERO_ERROR;
    updateFormatting(kFormattingNegSuffix, status);
}

UnicodeString &
DecimalFormatImpl::getPositivePrefix(UnicodeString &result) const {
    result = fAffixes.fPositivePrefix.getOtherVariant().toString();
    return result;
}

UnicodeString &
DecimalFormatImpl::getPositiveSuffix(UnicodeString &result) const {
    result = fAffixes.fPositiveSuffix.getOtherVariant().toString();
    return result;
}

UnicodeString &
DecimalFormatImpl::getNegativePrefix(UnicodeString &result) const {
    result = fAffixes.fNegativePrefix.getOtherVariant().toString();
    return result;
}

UnicodeString &
DecimalFormatImpl::getNegativeSuffix(UnicodeString &result) const {
    result = fAffixes.fNegativeSuffix.getOtherVariant().toString();
    return result;
}

void
DecimalFormatImpl::adoptDecimalFormatSymbols(DecimalFormatSymbols *symbolsToAdopt) {
    if (symbolsToAdopt == NULL) {
        return;
    }
    delete fSymbols;
    fSymbols = symbolsToAdopt;
    UErrorCode status = U_ZERO_ERROR;
    updateFormatting(kFormattingSymbols, status);
}

void
DecimalFormatImpl::applyPatternFavorCurrencyPrecision(
        const UnicodeString &pattern, UErrorCode &status) {
    UParseError perror;
    applyPattern(pattern, FALSE, perror, status);
    updateForApplyPatternFavorCurrencyPrecision(status);
}

void
DecimalFormatImpl::applyPattern(
        const UnicodeString &pattern, UErrorCode &status) {
    UParseError perror;
    applyPattern(pattern, FALSE, perror, status);
    updateForApplyPattern(status);
}

void
DecimalFormatImpl::applyPattern(
        const UnicodeString &pattern,
        UParseError &perror, UErrorCode &status) {
    applyPattern(pattern, FALSE, perror, status);
    updateForApplyPattern(status);
}

void
DecimalFormatImpl::applyLocalizedPattern(
        const UnicodeString &pattern, UErrorCode &status) {
    UParseError perror;
    applyPattern(pattern, TRUE, perror, status);
    updateForApplyPattern(status);
}

void
DecimalFormatImpl::applyLocalizedPattern(
        const UnicodeString &pattern,
        UParseError &perror,  UErrorCode &status) {
    applyPattern(pattern, TRUE, perror, status);
    updateForApplyPattern(status);
}

void
DecimalFormatImpl::applyPattern(
        const UnicodeString &pattern,
        UBool localized, UParseError &perror, UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    DecimalFormatPatternParser patternParser;
    if (localized) {
        patternParser.useSymbols(*fSymbols);
    }
    DecimalFormatPattern out;
    patternParser.applyPatternWithoutExpandAffix(
            pattern, out, perror, status);
    if (U_FAILURE(status)) {
        return;
    }
    fUseScientific = out.fUseExponentialNotation;
    fUseSigDigits = out.fUseSignificantDigits;
    fSuper->NumberFormat::setMinimumIntegerDigits(out.fMinimumIntegerDigits);
    fSuper->NumberFormat::setMaximumIntegerDigits(out.fMaximumIntegerDigits);
    fSuper->NumberFormat::setMinimumFractionDigits(out.fMinimumFractionDigits);
    fSuper->NumberFormat::setMaximumFractionDigits(out.fMaximumFractionDigits);
    fMinSigDigits = out.fMinimumSignificantDigits;
    fMaxSigDigits = out.fMaximumSignificantDigits;
    fEffPrecision.fMinExponentDigits = out.fMinExponentDigits;
    fOptions.fExponent.fAlwaysShowSign = out.fExponentSignAlwaysShown;
    fSuper->NumberFormat::setGroupingUsed(out.fGroupingUsed);
    fGrouping.fGrouping = out.fGroupingSize;
    fGrouping.fGrouping2 = out.fGroupingSize2;
    fOptions.fMantissa.fAlwaysShowDecimal = out.fDecimalSeparatorAlwaysShown;
    if (out.fRoundingIncrementUsed) {
        fEffPrecision.fMantissa.fRoundingIncrement = out.fRoundingIncrement;
    } else {
        fEffPrecision.fMantissa.fRoundingIncrement.clear();
    }
    fAffixes.fPadChar = out.fPad;
    fNegativePrefixPattern = out.fNegPrefixAffix;
    fNegativeSuffixPattern = out.fNegSuffixAffix;
    fPositivePrefixPattern = out.fPosPrefixAffix;
    fPositiveSuffixPattern = out.fPosSuffixAffix;

    // Work around. Pattern parsing code and DecimalFormat code don't agree
    // on the definition of field width, so we have to translate from
    // pattern field width to decimal format field width here.
    fAffixes.fWidth = out.fFormatWidth == 0 ? 0 :
            out.fFormatWidth + fPositivePrefixPattern.countChar32()
            + fPositiveSuffixPattern.countChar32();
    switch (out.fPadPosition) {
    case DecimalFormatPattern::kPadBeforePrefix:
        fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforePrefix;
        break;    
    case DecimalFormatPattern::kPadAfterPrefix:
        fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterPrefix;
        break;    
    case DecimalFormatPattern::kPadBeforeSuffix:
        fAffixes.fPadPosition = DigitAffixesAndPadding::kPadBeforeSuffix;
        break;    
    case DecimalFormatPattern::kPadAfterSuffix:
        fAffixes.fPadPosition = DigitAffixesAndPadding::kPadAfterSuffix;
        break;    
    default:
        break;
    }
}

void
DecimalFormatImpl::updatePrecision() {
    if (fUseScientific) {
        updatePrecisionForScientific();
    } else {
        updatePrecisionForFixed();
    }
}

static void updatePrecisionForScientificMinMax(
        const DigitInterval &min,
        const DigitInterval &max,
        DigitInterval &resultMin,
        DigitInterval &resultMax,
        SignificantDigitInterval &resultSignificant) {
    resultMin.setIntDigitCount(0);
    resultMin.setFracDigitCount(0);
    resultSignificant.clear();
    resultMax.clear();
    
    int32_t maxIntDigitCount = max.getIntDigitCount();
    int32_t minIntDigitCount = min.getIntDigitCount();
    int32_t maxFracDigitCount = max.getFracDigitCount();
    int32_t minFracDigitCount = min.getFracDigitCount();


    // Not in spec: maxIntDigitCount > 8 assume
    // maxIntDigitCount = minIntDigitCount. Current DecimalFormat API has
    // no provision for unsetting maxIntDigitCount which would be useful for
    // scientific notation. The best we can do is assume that if
    // maxIntDigitCount is the default of 2000000000 or is "big enough" then
    // user did not intend to explicitly set it. The 8 was derived emperically
    // by extensive testing of legacy code.
    if (maxIntDigitCount > 8) {
        maxIntDigitCount = minIntDigitCount;
    }

    // Per the spec, exponent grouping happens if maxIntDigitCount is more
    // than 1 and more than minIntDigitCount.
    UBool bExponentGrouping = maxIntDigitCount > 1 && minIntDigitCount < maxIntDigitCount;
    if (bExponentGrouping) {
        resultMax.setIntDigitCount(maxIntDigitCount);

        // For exponent grouping minIntDigits is always treated as 1 even
        // if it wasn't set to 1!
        resultMin.setIntDigitCount(1);
    } else {
        // Fixed digit count left of decimal. minIntDigitCount doesn't have
        // to equal maxIntDigitCount i.e minIntDigitCount == 0 while
        // maxIntDigitCount == 1.
        int32_t fixedIntDigitCount = maxIntDigitCount;

        // If fixedIntDigitCount is 0 but
        // min or max fraction count is 0 too then use 1. This way we can get
        // unlimited precision for X.XXXEX
        if (fixedIntDigitCount == 0 && (minFracDigitCount == 0 || maxFracDigitCount == 0)) {
            fixedIntDigitCount = 1;
        }
        resultMax.setIntDigitCount(fixedIntDigitCount);
        resultMin.setIntDigitCount(fixedIntDigitCount);
    }
    // Spec says this is how we compute significant digits. 0 means
    // unlimited significant digits.
    int32_t maxSigDigits = minIntDigitCount + maxFracDigitCount;
    if (maxSigDigits > 0) {
        int32_t minSigDigits = minIntDigitCount + minFracDigitCount;
        resultSignificant.setMin(minSigDigits);
        resultSignificant.setMax(maxSigDigits);
    }
}

void
DecimalFormatImpl::updatePrecisionForScientific() {
    FixedPrecision *result = &fEffPrecision.fMantissa;
    if (fUseSigDigits) {
        result->fMax.setFracDigitCount(-1);
        result->fMax.setIntDigitCount(1);
        result->fMin.setFracDigitCount(0);
        result->fMin.setIntDigitCount(1);
        result->fSignificant.clear();
        extractSigDigits(result->fSignificant);
        return;
    }
    DigitInterval max;
    DigitInterval min;
    extractMinMaxDigits(min, max);
    updatePrecisionForScientificMinMax(
            min, max,
            result->fMin, result->fMax, result->fSignificant);
}

void
DecimalFormatImpl::updatePrecisionForFixed() {
    FixedPrecision *result = &fEffPrecision.fMantissa;
    if (!fUseSigDigits) {
        extractMinMaxDigits(result->fMin, result->fMax);
        result->fSignificant.clear();
    } else {
        extractSigDigits(result->fSignificant);
        result->fMin.setIntDigitCount(1);
        result->fMin.setFracDigitCount(0);
        result->fMax.clear();
    }
}

void
 DecimalFormatImpl::extractMinMaxDigits(
        DigitInterval &min, DigitInterval &max) const {
    min.setIntDigitCount(fSuper->getMinimumIntegerDigits());
    max.setIntDigitCount(fSuper->getMaximumIntegerDigits());
    min.setFracDigitCount(fSuper->getMinimumFractionDigits());
    max.setFracDigitCount(fSuper->getMaximumFractionDigits());
}

void
 DecimalFormatImpl::extractSigDigits(
        SignificantDigitInterval &sig) const {
    sig.setMin(fMinSigDigits < 0 ? 0 : fMinSigDigits);
    sig.setMax(fMaxSigDigits < 0 ? 0 : fMaxSigDigits);
}

void
DecimalFormatImpl::updateGrouping() {
    if (fSuper->isGroupingUsed()) {
        fEffGrouping = fGrouping;
    } else {
        fEffGrouping.clear();
    }
}

void
DecimalFormatImpl::updateCurrency(UErrorCode &status) {
    updateFormatting(kFormattingCurrency, TRUE, status);
}

void
DecimalFormatImpl::updateFormatting(
        int32_t changedFormattingFields,
        UErrorCode &status) {
    updateFormatting(changedFormattingFields, TRUE, status);
}

void
DecimalFormatImpl::updateFormatting(
        int32_t changedFormattingFields,
        UBool updatePrecisionBasedOnCurrency,
        UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    // Each function updates one field. Order matters. For instance,
    // updatePluralRules comes before updateCurrencyAffixInfo because the
    // fRules field is needed to update the fCurrencyAffixInfo field.
    updateFormattingUsesCurrency(changedFormattingFields);
    updateFormattingFixedPointFormatter(changedFormattingFields);
    updateFormattingAffixParser(changedFormattingFields);
    updateFormattingPluralRules(changedFormattingFields, status);
    updateFormattingCurrencyAffixInfo(
            changedFormattingFields,
            updatePrecisionBasedOnCurrency,
            status);
    updateFormattingLocalizedPositivePrefix(
            changedFormattingFields, status);
    updateFormattingLocalizedPositiveSuffix(
            changedFormattingFields, status);
    updateFormattingLocalizedNegativePrefix(
            changedFormattingFields, status);
    updateFormattingLocalizedNegativeSuffix(
            changedFormattingFields, status);
}

void
DecimalFormatImpl::updateFormattingUsesCurrency(
        int32_t &changedFormattingFields) {
    if ((changedFormattingFields & kFormattingAffixes) == 0) {
        // If no affixes changed, don't need to do any work
        return;
    }
    UBool newUsesCurrency =
            fPositivePrefixPattern.usesCurrency() ||
            fPositiveSuffixPattern.usesCurrency() ||
            fNegativePrefixPattern.usesCurrency() ||
            fNegativeSuffixPattern.usesCurrency();
    if (fMonetary != newUsesCurrency) {
        fMonetary = newUsesCurrency;
        changedFormattingFields |= kFormattingUsesCurrency;
    }
}

void
DecimalFormatImpl::updateFormattingPluralRules(
        int32_t &changedFormattingFields, UErrorCode &status) {
    if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) {
        // No work to do if both fSymbols and fMonetary
        // fields are unchanged
        return;
    }
    if (U_FAILURE(status)) {
        return;
    }
    PluralRules *newRules = NULL;
    if (fMonetary) {
        newRules = PluralRules::forLocale(fSymbols->getLocale(), status);
        if (U_FAILURE(status)) {
            return;
        }
    }
    // Its ok to say a field has changed when it really hasn't but not
    // the other way around. Here we assume the field changed unless it
    // was NULL before and is still NULL now
    if (fRules != newRules) {
        delete fRules;
        fRules = newRules;
        changedFormattingFields |= kFormattingPluralRules;
    }
}

void
DecimalFormatImpl::updateFormattingCurrencyAffixInfo(
        int32_t &changedFormattingFields,
        UBool updatePrecisionBasedOnCurrency,
        UErrorCode &status) {
    if ((changedFormattingFields & (
            kFormattingSymbols | kFormattingCurrency |
            kFormattingUsesCurrency | kFormattingPluralRules)) == 0) {
        // If all these fields are unchanged, no work to do.
        return;
    }
    if (U_FAILURE(status)) {
        return;
    }
    if (!fMonetary) {
        if (fCurrencyAffixInfo.isDefault()) {
            // In this case don't have to do any work
            return;
        }
        fCurrencyAffixInfo.set(NULL, NULL, NULL, status);
        if (U_FAILURE(status)) {
            return;
        }
        changedFormattingFields |= kFormattingCurrencyAffixInfo;
    } else {
        const UChar *currency = fSuper->getCurrency();
        UChar localeCurr[4];
        if (currency[0] == 0) {
            ucurr_forLocale(fSymbols->getLocale().getName(), localeCurr, UPRV_LENGTHOF(localeCurr), &status);
            if (U_SUCCESS(status)) {
                currency = localeCurr;
                fSuper->NumberFormat::setCurrency(currency, status);
            } else {
                currency = NULL;
                status = U_ZERO_ERROR;
            }
        }
        fCurrencyAffixInfo.set(
                fSymbols->getLocale().getName(), fRules, currency, status);
        if (U_FAILURE(status)) {
            return;
        }
        UBool customCurrencySymbol = FALSE;
        // If DecimalFormatSymbols has custom currency symbol, prefer
        // that over what we just read from the resource bundles
        if (fSymbols->isCustomCurrencySymbol()) {
            fCurrencyAffixInfo.setSymbol(
                    fSymbols->getConstSymbol(DecimalFormatSymbols::kCurrencySymbol));
            customCurrencySymbol = TRUE;
        }
        if (fSymbols->isCustomIntlCurrencySymbol()) {
            fCurrencyAffixInfo.setISO(
                    fSymbols->getConstSymbol(DecimalFormatSymbols::kIntlCurrencySymbol));
            customCurrencySymbol = TRUE;
        }
        changedFormattingFields |= kFormattingCurrencyAffixInfo;
        if (currency && !customCurrencySymbol && updatePrecisionBasedOnCurrency) {
            FixedPrecision precision;
            CurrencyAffixInfo::adjustPrecision(
                    currency, fCurrencyUsage, precision, status);
            if (U_FAILURE(status)) {
                return;
            }
            fSuper->NumberFormat::setMinimumFractionDigits(
                    precision.fMin.getFracDigitCount());
            fSuper->NumberFormat::setMaximumFractionDigits(
                    precision.fMax.getFracDigitCount());
            updatePrecision();
            fEffPrecision.fMantissa.fRoundingIncrement =
                    precision.fRoundingIncrement;
        }
 
    }
}

void
DecimalFormatImpl::updateFormattingFixedPointFormatter(
        int32_t &changedFormattingFields) {
    if ((changedFormattingFields & (kFormattingSymbols | kFormattingUsesCurrency)) == 0) {
        // No work to do if fSymbols is unchanged
        return;
    }
    if (fMonetary) {
        fFormatter.setDecimalFormatSymbolsForMonetary(*fSymbols);
    } else {
        fFormatter.setDecimalFormatSymbols(*fSymbols);
    }
}

void
DecimalFormatImpl::updateFormattingAffixParser(
        int32_t &changedFormattingFields) {
    if ((changedFormattingFields & kFormattingSymbols) == 0) {
        // No work to do if fSymbols is unchanged
        return;
    }
    fAffixParser.setDecimalFormatSymbols(*fSymbols);
    changedFormattingFields |= kFormattingAffixParser;
}

void
DecimalFormatImpl::updateFormattingLocalizedPositivePrefix(
        int32_t &changedFormattingFields, UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    if ((changedFormattingFields & (
            kFormattingPosPrefix | kFormattingAffixParserWithCurrency)) == 0) {
        // No work to do
        return;
    }
    fAffixes.fPositivePrefix.remove();
    fAffixParser.parse(
            fPositivePrefixPattern,
            fCurrencyAffixInfo,
            fAffixes.fPositivePrefix,
            status);
}

void
DecimalFormatImpl::updateFormattingLocalizedPositiveSuffix(
        int32_t &changedFormattingFields, UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    if ((changedFormattingFields & (
            kFormattingPosSuffix | kFormattingAffixParserWithCurrency)) == 0) {
        // No work to do
        return;
    }
    fAffixes.fPositiveSuffix.remove();
    fAffixParser.parse(
            fPositiveSuffixPattern,
            fCurrencyAffixInfo,
            fAffixes.fPositiveSuffix,
            status);
}

void
DecimalFormatImpl::updateFormattingLocalizedNegativePrefix(
        int32_t &changedFormattingFields, UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    if ((changedFormattingFields & (
            kFormattingNegPrefix | kFormattingAffixParserWithCurrency)) == 0) {
        // No work to do
        return;
    }
    fAffixes.fNegativePrefix.remove();
    fAffixParser.parse(
            fNegativePrefixPattern,
            fCurrencyAffixInfo,
            fAffixes.fNegativePrefix,
            status);
}

void
DecimalFormatImpl::updateFormattingLocalizedNegativeSuffix(
        int32_t &changedFormattingFields, UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    if ((changedFormattingFields & (
            kFormattingNegSuffix | kFormattingAffixParserWithCurrency)) == 0) {
        // No work to do
        return;
    }
    fAffixes.fNegativeSuffix.remove();
    fAffixParser.parse(
            fNegativeSuffixPattern,
            fCurrencyAffixInfo,
            fAffixes.fNegativeSuffix,
            status);
}

void
DecimalFormatImpl::updateForApplyPatternFavorCurrencyPrecision(
        UErrorCode &status) {
    updateAll(kFormattingAll & ~kFormattingSymbols, TRUE, status);
}

void
DecimalFormatImpl::updateForApplyPattern(UErrorCode &status) {
    updateAll(kFormattingAll & ~kFormattingSymbols, FALSE, status);
}

void
DecimalFormatImpl::updateAll(UErrorCode &status) {
    updateAll(kFormattingAll, TRUE, status);
}

void
DecimalFormatImpl::updateAll(
        int32_t formattingFlags,
        UBool updatePrecisionBasedOnCurrency,
        UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    updatePrecision();
    updateGrouping();
    updateFormatting(
            formattingFlags, updatePrecisionBasedOnCurrency, status);
    setMultiplierScale(getPatternScale());
}


static int32_t
getMinimumLengthToDescribeGrouping(const DigitGrouping &grouping) {
    if (grouping.fGrouping <= 0) {
        return 0;
    }
    if (grouping.fGrouping2 <= 0) {
        return grouping.fGrouping + 1;
    }
    return grouping.fGrouping + grouping.fGrouping2 + 1;
}

/**
 * Given a grouping policy, calculates how many digits are needed left of
 * the decimal point to achieve a desired length left of the
 * decimal point.
 * @param grouping the grouping policy
 * @param desiredLength number of characters needed left of decimal point
 * @param minLeftDigits at least this many digits is returned
 * @param leftDigits the number of digits needed stored here
 *  which is >= minLeftDigits.
 * @return true if a perfect fit or false if having leftDigits would exceed
 *   desiredLength
 */
static UBool
getLeftDigitsForLeftLength(
        const DigitGrouping &grouping,
        int32_t desiredLength,
        int32_t minLeftDigits,
        int32_t &leftDigits) {
    leftDigits = minLeftDigits;
    int32_t lengthSoFar = leftDigits + grouping.getSeparatorCount(leftDigits);
    while (lengthSoFar < desiredLength) {
        lengthSoFar += grouping.isSeparatorAt(leftDigits + 1, leftDigits) ? 2 : 1;
        ++leftDigits;
    }
    return (lengthSoFar == desiredLength);
}

int32_t
DecimalFormatImpl::computeExponentPatternLength() const {
    if (fUseScientific) {
        return 1 + (fOptions.fExponent.fAlwaysShowSign ? 1 : 0) + fEffPrecision.fMinExponentDigits;
    }
    return 0;
}

int32_t
DecimalFormatImpl::countFractionDigitAndDecimalPatternLength(
        int32_t fracDigitCount) const {
    if (!fOptions.fMantissa.fAlwaysShowDecimal && fracDigitCount == 0) {
        return 0;
    }
    return fracDigitCount + 1;
}

UnicodeString&
DecimalFormatImpl::toNumberPattern(
        UBool hasPadding, int32_t minimumLength, UnicodeString& result) const {
    // Get a grouping policy like the one in this object that does not
    // have minimum grouping since toPattern doesn't support it.
    DigitGrouping grouping(fEffGrouping);
    grouping.fMinGrouping = 0;

    // Only for fixed digits, these are the digits that get 0's.
    DigitInterval minInterval;

    // Only for fixed digits, these are the digits that get #'s.
    DigitInterval maxInterval;

    // Only for significant digits
    int32_t sigMin;
    int32_t sigMax;

    // These are all the digits to be displayed. For significant digits,
    // this interval always starts at the 1's place an extends left.
    DigitInterval fullInterval;

    // Digit range of rounding increment. If rounding increment is .025.
    // then roundingIncrementLowerExp = -3 and roundingIncrementUpperExp = -1
    int32_t roundingIncrementLowerExp = 0;
    int32_t roundingIncrementUpperExp = 0;

    if (fUseSigDigits) {
        SignificantDigitInterval sigInterval;
        extractSigDigits(sigInterval);
        sigMax = sigInterval.getMax();
        sigMin = sigInterval.getMin();
        fullInterval.setFracDigitCount(0);
        fullInterval.setIntDigitCount(sigMax);
    } else {
        extractMinMaxDigits(minInterval, maxInterval);
        if (fUseScientific) {
           if (maxInterval.getIntDigitCount() > kMaxScientificIntegerDigits) {
               maxInterval.setIntDigitCount(1);
               minInterval.shrinkToFitWithin(maxInterval);
           }
        } else if (hasPadding) {
            // Make max int digits match min int digits for now, we
            // compute necessary padding later.
            maxInterval.setIntDigitCount(minInterval.getIntDigitCount());
        } else {
            // For some reason toPattern adds at least one leading '#'
            maxInterval.setIntDigitCount(minInterval.getIntDigitCount() + 1);
        }
        if (!fEffPrecision.fMantissa.fRoundingIncrement.isZero()) {
            roundingIncrementLowerExp = 
                    fEffPrecision.fMantissa.fRoundingIncrement.getLowerExponent();
            roundingIncrementUpperExp = 
                    fEffPrecision.fMantissa.fRoundingIncrement.getUpperExponent();
            // We have to include the rounding increment in what we display
            maxInterval.expandToContainDigit(roundingIncrementLowerExp);
            maxInterval.expandToContainDigit(roundingIncrementUpperExp - 1);
        }
        fullInterval = maxInterval;
    }
    // We have to include enough digits to show grouping strategy
    int32_t minLengthToDescribeGrouping =
           getMinimumLengthToDescribeGrouping(grouping);
    if (minLengthToDescribeGrouping > 0) {
        fullInterval.expandToContainDigit(
                getMinimumLengthToDescribeGrouping(grouping) - 1);
    }

    // If we have a minimum length, we have to add digits to the left to
    // depict padding.
    if (hasPadding) {
        // For non scientific notation,
        //  minimumLengthForMantissa = minimumLength
        int32_t minimumLengthForMantissa = 
                minimumLength - computeExponentPatternLength();
        int32_t mininumLengthForMantissaIntPart =
                minimumLengthForMantissa
                - countFractionDigitAndDecimalPatternLength(
                        fullInterval.getFracDigitCount());
        // Because of grouping, we may need fewer than expected digits to
        // achieve the length we need.
        int32_t digitsNeeded;
        if (getLeftDigitsForLeftLength(
                grouping,
                mininumLengthForMantissaIntPart,
                fullInterval.getIntDigitCount(),
                digitsNeeded)) {

            // In this case, we achieved the exact length that we want.
            fullInterval.setIntDigitCount(digitsNeeded);
        } else if (digitsNeeded > fullInterval.getIntDigitCount()) {

            // Having digitsNeeded digits goes over desired length which
            // means that to have desired length would mean starting on a
            // grouping sepearator e.g ,###,### so add a '#' and use one
            // less digit. This trick gives ####,### but that is the best
            // we can do.
            result.append(kPatternDigit);
            fullInterval.setIntDigitCount(digitsNeeded - 1);
        }
    }
    int32_t maxDigitPos = fullInterval.getMostSignificantExclusive();
    int32_t minDigitPos = fullInterval.getLeastSignificantInclusive();
    for (int32_t i = maxDigitPos - 1; i >= minDigitPos; --i) {
        if (!fOptions.fMantissa.fAlwaysShowDecimal && i == -1) {
            result.append(kPatternDecimalSeparator);
        }
        if (fUseSigDigits) {
            // Use digit symbol
            if (i >= sigMax || i < sigMax - sigMin) {
                result.append(kPatternDigit);
            } else {
                result.append(kPatternSignificantDigit);
            }
        } else {
            if (i < roundingIncrementUpperExp && i >= roundingIncrementLowerExp) {
                result.append(fEffPrecision.fMantissa.fRoundingIncrement.getDigitByExponent(i) + kPatternZeroDigit);
            } else if (minInterval.contains(i)) {
                result.append(kPatternZeroDigit);
            } else {
                result.append(kPatternDigit);
            }
        }
        if (grouping.isSeparatorAt(i + 1, i)) {
            result.append(kPatternGroupingSeparator);
        }
        if (fOptions.fMantissa.fAlwaysShowDecimal && i == 0) {
            result.append(kPatternDecimalSeparator);
        }
    }
    if (fUseScientific) {
        result.append(kPatternExponent);
        if (fOptions.fExponent.fAlwaysShowSign) {
            result.append(kPatternPlus);
        }
        for (int32_t i = 0; i < 1 || i < fEffPrecision.fMinExponentDigits; ++i) {
            result.append(kPatternZeroDigit);
        }
    }
    return result;
}

UnicodeString&
DecimalFormatImpl::toPattern(UnicodeString& result) const {
    result.remove();
    UnicodeString padSpec;
    if (fAffixes.fWidth > 0) {
        padSpec.append(kPatternPadEscape);
        padSpec.append(fAffixes.fPadChar);
    }
    if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
        result.append(padSpec);
    }
    fPositivePrefixPattern.toUserString(result);
    if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
        result.append(padSpec);
    }
    toNumberPattern(
            fAffixes.fWidth > 0,
            fAffixes.fWidth - fPositivePrefixPattern.countChar32() - fPositiveSuffixPattern.countChar32(),
            result);
    if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
        result.append(padSpec);
    }
    fPositiveSuffixPattern.toUserString(result);
    if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
        result.append(padSpec);
    }
    AffixPattern withNegative;
    withNegative.add(AffixPattern::kNegative);
    withNegative.append(fPositivePrefixPattern);
    if (!fPositiveSuffixPattern.equals(fNegativeSuffixPattern) ||
            !withNegative.equals(fNegativePrefixPattern)) {
        result.append(kPatternSeparator);
        if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforePrefix) {
            result.append(padSpec);
        }
        fNegativePrefixPattern.toUserString(result);
        if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterPrefix) {
            result.append(padSpec);
        }
        toNumberPattern(
                fAffixes.fWidth > 0,
                fAffixes.fWidth - fNegativePrefixPattern.countChar32() - fNegativeSuffixPattern.countChar32(),
                result);
        if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadBeforeSuffix) {
            result.append(padSpec);
        }
        fNegativeSuffixPattern.toUserString(result);
        if (fAffixes.fPadPosition == DigitAffixesAndPadding::kPadAfterSuffix) {
            result.append(padSpec);
        }
    }
    return result;
}

int32_t
DecimalFormatImpl::getOldFormatWidth() const {
    if (fAffixes.fWidth == 0) {
        return 0;
    }
    return fAffixes.fWidth - fPositiveSuffixPattern.countChar32() - fPositivePrefixPattern.countChar32();
}

const UnicodeString &
DecimalFormatImpl::getConstSymbol(
        DecimalFormatSymbols::ENumberFormatSymbol symbol) const {
   return fSymbols->getConstSymbol(symbol); 
}

UBool
DecimalFormatImpl::isParseFastpath() const {
    AffixPattern negative;
    negative.add(AffixPattern::kNegative);

    return fAffixes.fWidth == 0 &&
    fPositivePrefixPattern.countChar32() == 0 &&
    fNegativePrefixPattern.equals(negative) &&
    fPositiveSuffixPattern.countChar32() == 0 &&
    fNegativeSuffixPattern.countChar32() == 0;
}


U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */

