// © 2018 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

// Allow implicit conversion from char16_t* to UnicodeString for this file:
// Helpful in toString methods and elsewhere.
#define UNISTR_FROM_STRING_EXPLICIT

#include <cmath>
#include <cstdlib>
#include <stdlib.h>
#include "unicode/errorcode.h"
#include "unicode/decimfmt.h"
#include "number_decimalquantity.h"
#include "number_types.h"
#include "numparse_impl.h"
#include "number_mapper.h"
#include "number_patternstring.h"
#include "putilimp.h"
#include "number_utils.h"
#include "number_utypes.h"

using namespace icu;
using namespace icu::number;
using namespace icu::number::impl;
using namespace icu::numparse;
using namespace icu::numparse::impl;
using ERoundingMode = icu::DecimalFormat::ERoundingMode;
using EPadPosition = icu::DecimalFormat::EPadPosition;

// MSVC VS2015 warns C4805 when comparing bool with UBool, VS2017 no longer emits this warning.
// TODO: Move this macro into a better place?
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
#define UBOOL_TO_BOOL(b) static_cast<bool>(b)
#else
#define UBOOL_TO_BOOL(b) b
#endif


UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormat)


DecimalFormat::DecimalFormat(UErrorCode& status)
        : DecimalFormat(nullptr, status) {
    if (U_FAILURE(status)) { return; }
    // Use the default locale and decimal pattern.
    const char* localeName = Locale::getDefault().getName();
    LocalPointer<NumberingSystem> ns(NumberingSystem::createInstance(status));
    UnicodeString patternString = utils::getPatternForStyle(
            localeName,
            ns->getName(),
            CLDR_PATTERN_STYLE_DECIMAL,
            status);
    setPropertiesFromPattern(patternString, IGNORE_ROUNDING_IF_CURRENCY, status);
    touch(status);
}

DecimalFormat::DecimalFormat(const UnicodeString& pattern, UErrorCode& status)
        : DecimalFormat(nullptr, status) {
    if (U_FAILURE(status)) { return; }
    setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status);
    touch(status);
}

DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
                             UErrorCode& status)
        : DecimalFormat(symbolsToAdopt, status) {
    if (U_FAILURE(status)) { return; }
    setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status);
    touch(status);
}

DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
                             UNumberFormatStyle style, UErrorCode& status)
        : DecimalFormat(symbolsToAdopt, status) {
    if (U_FAILURE(status)) { return; }
    // If choice is a currency type, ignore the rounding information.
    if (style == UNumberFormatStyle::UNUM_CURRENCY ||
        style == UNumberFormatStyle::UNUM_CURRENCY_ISO ||
        style == UNumberFormatStyle::UNUM_CURRENCY_ACCOUNTING ||
        style == UNumberFormatStyle::UNUM_CASH_CURRENCY ||
        style == UNumberFormatStyle::UNUM_CURRENCY_STANDARD ||
        style == UNumberFormatStyle::UNUM_CURRENCY_PLURAL) {
        setPropertiesFromPattern(pattern, IGNORE_ROUNDING_ALWAYS, status);
    } else {
        setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status);
    }
    // Note: in Java, CurrencyPluralInfo is set in NumberFormat.java, but in C++, it is not set there,
    // so we have to set it here.
    if (style == UNumberFormatStyle::UNUM_CURRENCY_PLURAL) {
        LocalPointer<CurrencyPluralInfo> cpi(
                new CurrencyPluralInfo(fields->symbols->getLocale(), status),
                status);
        if (U_FAILURE(status)) { return; }
        fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
    }
    touch(status);
}

DecimalFormat::DecimalFormat(const DecimalFormatSymbols* symbolsToAdopt, UErrorCode& status) {
    // we must take ownership of symbolsToAdopt, even in a failure case.
    LocalPointer<const DecimalFormatSymbols> adoptedSymbols(symbolsToAdopt);
    if (U_FAILURE(status)) {
        return;
    }
    fields = new DecimalFormatFields();
    if (fields == nullptr) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status);
    fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
    fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
    if (adoptedSymbols.isNull()) {
        fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(status), status);
    } else {
        fields->symbols.adoptInsteadAndCheckErrorCode(adoptedSymbols.orphan(), status);
    }
    // In order to simplify error handling logic in the various getters/setters/etc, we do not allow
    // any partially populated DecimalFormatFields object. We must have a fully complete fields object
    // or else we set it to nullptr.
    if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) {
        delete fields;
        fields = nullptr;
        status = U_MEMORY_ALLOCATION_ERROR;
    }
}

#if UCONFIG_HAVE_PARSEALLINPUT

void DecimalFormat::setParseAllInput(UNumberFormatAttributeValue value) {
    if (fields == nullptr) { return; }
    if (value == fields->properties->parseAllInput) { return; }
    fields->properties->parseAllInput = value;
}

#endif

DecimalFormat&
DecimalFormat::setAttribute(UNumberFormatAttribute attr, int32_t newValue, UErrorCode& status) {
    if (U_FAILURE(status)) { return *this; }

    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        return *this;
    }

    switch (attr) {
        case UNUM_LENIENT_PARSE:
            setLenient(newValue != 0);
            break;

        case UNUM_PARSE_INT_ONLY:
            setParseIntegerOnly(newValue != 0);
            break;

        case UNUM_GROUPING_USED:
            setGroupingUsed(newValue != 0);
            break;

        case UNUM_DECIMAL_ALWAYS_SHOWN:
            setDecimalSeparatorAlwaysShown(newValue != 0);
            break;

        case UNUM_MAX_INTEGER_DIGITS:
            setMaximumIntegerDigits(newValue);
            break;

        case UNUM_MIN_INTEGER_DIGITS:
            setMinimumIntegerDigits(newValue);
            break;

        case UNUM_INTEGER_DIGITS:
            setMinimumIntegerDigits(newValue);
            setMaximumIntegerDigits(newValue);
            break;

        case UNUM_MAX_FRACTION_DIGITS:
            setMaximumFractionDigits(newValue);
            break;

        case UNUM_MIN_FRACTION_DIGITS:
            setMinimumFractionDigits(newValue);
            break;

        case UNUM_FRACTION_DIGITS:
            setMinimumFractionDigits(newValue);
            setMaximumFractionDigits(newValue);
            break;

        case UNUM_SIGNIFICANT_DIGITS_USED:
            setSignificantDigitsUsed(newValue != 0);
            break;

        case UNUM_MAX_SIGNIFICANT_DIGITS:
            setMaximumSignificantDigits(newValue);
            break;

        case UNUM_MIN_SIGNIFICANT_DIGITS:
            setMinimumSignificantDigits(newValue);
            break;

        case UNUM_MULTIPLIER:
            setMultiplier(newValue);
            break;

        case UNUM_SCALE:
            setMultiplierScale(newValue);
            break;

        case UNUM_GROUPING_SIZE:
            setGroupingSize(newValue);
            break;

        case UNUM_ROUNDING_MODE:
            setRoundingMode((DecimalFormat::ERoundingMode) newValue);
            break;

        case UNUM_FORMAT_WIDTH:
            setFormatWidth(newValue);
            break;

        case UNUM_PADDING_POSITION:
            /** The position at which padding will take place. */
            setPadPosition((DecimalFormat::EPadPosition) newValue);
            break;

        case UNUM_SECONDARY_GROUPING_SIZE:
            setSecondaryGroupingSize(newValue);
            break;

#if UCONFIG_HAVE_PARSEALLINPUT
        case UNUM_PARSE_ALL_INPUT:
            setParseAllInput((UNumberFormatAttributeValue) newValue);
            break;
#endif

        case UNUM_PARSE_NO_EXPONENT:
            setParseNoExponent((UBool) newValue);
            break;

        case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
            setDecimalPatternMatchRequired((UBool) newValue);
            break;

        case UNUM_CURRENCY_USAGE:
            setCurrencyUsage((UCurrencyUsage) newValue, &status);
            break;

        case UNUM_MINIMUM_GROUPING_DIGITS:
            setMinimumGroupingDigits(newValue);
            break;

        case UNUM_PARSE_CASE_SENSITIVE:
            setParseCaseSensitive(static_cast<UBool>(newValue));
            break;

        case UNUM_SIGN_ALWAYS_SHOWN:
            setSignAlwaysShown(static_cast<UBool>(newValue));
            break;

        case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
            setFormatFailIfMoreThanMaxDigits(static_cast<UBool>(newValue));
            break;

        default:
            status = U_UNSUPPORTED_ERROR;
            break;
    }
    return *this;
}

int32_t DecimalFormat::getAttribute(UNumberFormatAttribute attr, UErrorCode& status) const {
    if (U_FAILURE(status)) { return -1; }
    
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        return -1;
    }

    switch (attr) {
        case UNUM_LENIENT_PARSE:
            return isLenient();

        case UNUM_PARSE_INT_ONLY:
            return isParseIntegerOnly();

        case UNUM_GROUPING_USED:
            return isGroupingUsed();

        case UNUM_DECIMAL_ALWAYS_SHOWN:
            return isDecimalSeparatorAlwaysShown();

        case UNUM_MAX_INTEGER_DIGITS:
            return getMaximumIntegerDigits();

        case UNUM_MIN_INTEGER_DIGITS:
            return getMinimumIntegerDigits();

        case UNUM_INTEGER_DIGITS:
            // TBD: what should this return?
            return getMinimumIntegerDigits();

        case UNUM_MAX_FRACTION_DIGITS:
            return getMaximumFractionDigits();

        case UNUM_MIN_FRACTION_DIGITS:
            return getMinimumFractionDigits();

        case UNUM_FRACTION_DIGITS:
            // TBD: what should this return?
            return getMinimumFractionDigits();

        case UNUM_SIGNIFICANT_DIGITS_USED:
            return areSignificantDigitsUsed();

        case UNUM_MAX_SIGNIFICANT_DIGITS:
            return getMaximumSignificantDigits();

        case UNUM_MIN_SIGNIFICANT_DIGITS:
            return getMinimumSignificantDigits();

        case UNUM_MULTIPLIER:
            return getMultiplier();

        case UNUM_SCALE:
            return getMultiplierScale();

        case UNUM_GROUPING_SIZE:
            return getGroupingSize();

        case UNUM_ROUNDING_MODE:
            return getRoundingMode();

        case UNUM_FORMAT_WIDTH:
            return getFormatWidth();

        case UNUM_PADDING_POSITION:
            return getPadPosition();

        case UNUM_SECONDARY_GROUPING_SIZE:
            return getSecondaryGroupingSize();

        case UNUM_PARSE_NO_EXPONENT:
            return isParseNoExponent();

        case UNUM_PARSE_DECIMAL_MARK_REQUIRED:
            return isDecimalPatternMatchRequired();

        case UNUM_CURRENCY_USAGE:
            return getCurrencyUsage();

        case UNUM_MINIMUM_GROUPING_DIGITS:
            return getMinimumGroupingDigits();

        case UNUM_PARSE_CASE_SENSITIVE:
            return isParseCaseSensitive();

        case UNUM_SIGN_ALWAYS_SHOWN:
            return isSignAlwaysShown();

        case UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS:
            return isFormatFailIfMoreThanMaxDigits();

        default:
            status = U_UNSUPPORTED_ERROR;
            break;
    }

    return -1; /* undefined */
}

void DecimalFormat::setGroupingUsed(UBool enabled) {
    if (fields == nullptr) {
        return;
    }
    if (UBOOL_TO_BOOL(enabled) == fields->properties->groupingUsed) { return; }
    NumberFormat::setGroupingUsed(enabled); // to set field for compatibility
    fields->properties->groupingUsed = enabled;
    touchNoError();
}

void DecimalFormat::setParseIntegerOnly(UBool value) {
    if (fields == nullptr) {
        return;
    }
    if (UBOOL_TO_BOOL(value) == fields->properties->parseIntegerOnly) { return; }
    NumberFormat::setParseIntegerOnly(value); // to set field for compatibility
    fields->properties->parseIntegerOnly = value;
    touchNoError();
}

void DecimalFormat::setLenient(UBool enable) {
    if (fields == nullptr) {
        return;
    }
    ParseMode mode = enable ? PARSE_MODE_LENIENT : PARSE_MODE_STRICT;
    if (!fields->properties->parseMode.isNull() && mode == fields->properties->parseMode.getNoError()) { return; }
    NumberFormat::setLenient(enable); // to set field for compatibility
    fields->properties->parseMode = mode;
    touchNoError();
}

DecimalFormat::DecimalFormat(const UnicodeString& pattern, DecimalFormatSymbols* symbolsToAdopt,
                             UParseError&, UErrorCode& status)
        : DecimalFormat(symbolsToAdopt, status) {
    if (U_FAILURE(status)) { return; }
    // TODO: What is parseError for?
    setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status);
    touch(status);
}

DecimalFormat::DecimalFormat(const UnicodeString& pattern, const DecimalFormatSymbols& symbols,
                             UErrorCode& status)
        : DecimalFormat(nullptr, status) {
    if (U_FAILURE(status)) { return; }
    LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(symbols), status);
    if (U_FAILURE(status)) {
        // If we failed to allocate DecimalFormatSymbols, then release fields and its members.
        // We must have a fully complete fields object, we cannot have partially populated members.
        delete fields;
        fields = nullptr;
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    fields->symbols.adoptInstead(dfs.orphan());
    setPropertiesFromPattern(pattern, IGNORE_ROUNDING_IF_CURRENCY, status);
    touch(status);
}

DecimalFormat::DecimalFormat(const DecimalFormat& source) : NumberFormat(source) {
    // If the object that we are copying from is invalid, no point in going further.
    if (source.fields == nullptr) {
        return;
    }
    // Note: it is not safe to copy fields->formatter or fWarehouse directly because fields->formatter might have
    // dangling pointers to fields inside fWarehouse. The safe thing is to re-construct fields->formatter from
    // the property bag, despite being somewhat slower.
    fields = new DecimalFormatFields();
    if (fields == nullptr) {
        return; // no way to report an error.
    }
    UErrorCode status = U_ZERO_ERROR;
    fields->formatter.adoptInsteadAndCheckErrorCode(new LocalizedNumberFormatter(), status);
    fields->properties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(*source.fields->properties), status);
    fields->symbols.adoptInsteadAndCheckErrorCode(new DecimalFormatSymbols(*source.fields->symbols), status);
    fields->exportedProperties.adoptInsteadAndCheckErrorCode(new DecimalFormatProperties(), status);
    // In order to simplify error handling logic in the various getters/setters/etc, we do not allow
    // any partially populated DecimalFormatFields object. We must have a fully complete fields object
    // or else we set it to nullptr.
    if (fields->formatter.isNull() || fields->properties.isNull() || fields->exportedProperties.isNull() || fields->symbols.isNull()) {
        delete fields;
        fields = nullptr;
        return;
    }
    touch(status);
}

DecimalFormat& DecimalFormat::operator=(const DecimalFormat& rhs) {
    // guard against self-assignment
    if (this == &rhs) {
        return *this;
    }
    // Make sure both objects are valid.
    if (fields == nullptr || rhs.fields == nullptr) {
        return *this; // unfortunately, no way to report an error.
    }
    *fields->properties = *rhs.fields->properties;
    fields->exportedProperties->clear();
    UErrorCode status = U_ZERO_ERROR;
    LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(*rhs.fields->symbols), status);
    if (U_FAILURE(status)) {
        // We failed to allocate DecimalFormatSymbols, release fields and its members.
        // We must have a fully complete fields object, we cannot have partially populated members.
        delete fields;
        fields = nullptr;
        return *this;
    }
    fields->symbols.adoptInstead(dfs.orphan());
    touch(status);

    return *this;
}

DecimalFormat::~DecimalFormat() {
    if (fields == nullptr) { return; }

    delete fields->atomicParser.exchange(nullptr);
    delete fields->atomicCurrencyParser.exchange(nullptr);
    delete fields;
}

Format* DecimalFormat::clone() const {
    // can only clone valid objects.
    if (fields == nullptr) {
        return nullptr;
    }
    LocalPointer<DecimalFormat> df(new DecimalFormat(*this));
    if (df.isValid() && df->fields != nullptr) {
        return df.orphan();
    }
    return nullptr;
}

UBool DecimalFormat::operator==(const Format& other) const {
    auto* otherDF = dynamic_cast<const DecimalFormat*>(&other);
    if (otherDF == nullptr) {
        return false;
    }
    // If either object is in an invalid state, prevent dereferencing nullptr below.
    // Additionally, invalid objects should not be considered equal to anything.
    if (fields == nullptr || otherDF->fields == nullptr) {
        return false;
    }
    return *fields->properties == *otherDF->fields->properties && *fields->symbols == *otherDF->fields->symbols;
}

UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos) const {
    if (fields == nullptr) {
        appendTo.setToBogus();
        return appendTo;
    }
    if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) {
        return appendTo;
    }
    UErrorCode localStatus = U_ZERO_ERROR;
    FormattedNumber output = fields->formatter->formatDouble(number, localStatus);
    fieldPositionHelper(output, pos, appendTo.length(), localStatus);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, localStatus);
    return appendTo;
}

UnicodeString& DecimalFormat::format(double number, UnicodeString& appendTo, FieldPosition& pos,
                                     UErrorCode& status) const {
    if (U_FAILURE(status)) {
        return appendTo; // don't overwrite status if it's already a failure.
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        appendTo.setToBogus();
        return appendTo;
    }
    if (pos.getField() == FieldPosition::DONT_CARE && fastFormatDouble(number, appendTo)) {
        return appendTo;
    }
    FormattedNumber output = fields->formatter->formatDouble(number, status);
    fieldPositionHelper(output, pos, appendTo.length(), status);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, status);
    return appendTo;
}

UnicodeString&
DecimalFormat::format(double number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                      UErrorCode& status) const {
    if (U_FAILURE(status)) {
        return appendTo; // don't overwrite status if it's already a failure.
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        appendTo.setToBogus();
        return appendTo;
    }
    if (posIter == nullptr && fastFormatDouble(number, appendTo)) {
        return appendTo;
    }
    FormattedNumber output = fields->formatter->formatDouble(number, status);
    fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, status);
    return appendTo;
}

UnicodeString& DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos) const {
    return format(static_cast<int64_t> (number), appendTo, pos);
}

UnicodeString& DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPosition& pos,
                                     UErrorCode& status) const {
    return format(static_cast<int64_t> (number), appendTo, pos, status);
}

UnicodeString&
DecimalFormat::format(int32_t number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                      UErrorCode& status) const {
    return format(static_cast<int64_t> (number), appendTo, posIter, status);
}

UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos) const {
    if (fields == nullptr) {
        appendTo.setToBogus();
        return appendTo;
    }
    if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) {
        return appendTo;
    }
    UErrorCode localStatus = U_ZERO_ERROR;
    FormattedNumber output = fields->formatter->formatInt(number, localStatus);
    fieldPositionHelper(output, pos, appendTo.length(), localStatus);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, localStatus);
    return appendTo;
}

UnicodeString& DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPosition& pos,
                                     UErrorCode& status) const {
    if (U_FAILURE(status)) {
        return appendTo; // don't overwrite status if it's already a failure.
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        appendTo.setToBogus();
        return appendTo;
    }
    if (pos.getField() == FieldPosition::DONT_CARE && fastFormatInt64(number, appendTo)) {
        return appendTo;
    }
    FormattedNumber output = fields->formatter->formatInt(number, status);
    fieldPositionHelper(output, pos, appendTo.length(), status);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, status);
    return appendTo;
}

UnicodeString&
DecimalFormat::format(int64_t number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                      UErrorCode& status) const {
    if (U_FAILURE(status)) {
        return appendTo; // don't overwrite status if it's already a failure.
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        appendTo.setToBogus();
        return appendTo;
    }
    if (posIter == nullptr && fastFormatInt64(number, appendTo)) {
        return appendTo;
    }
    FormattedNumber output = fields->formatter->formatInt(number, status);
    fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, status);
    return appendTo;
}

UnicodeString&
DecimalFormat::format(StringPiece number, UnicodeString& appendTo, FieldPositionIterator* posIter,
                      UErrorCode& status) const {
    if (U_FAILURE(status)) {
        return appendTo; // don't overwrite status if it's already a failure.
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        appendTo.setToBogus();
        return appendTo;
    }
    FormattedNumber output = fields->formatter->formatDecimal(number, status);
    fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, status);
    return appendTo;
}

UnicodeString& DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo,
                                     FieldPositionIterator* posIter, UErrorCode& status) const {
    if (U_FAILURE(status)) {
        return appendTo; // don't overwrite status if it's already a failure.
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        appendTo.setToBogus();
        return appendTo;
    }
    FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status);
    fieldPositionIteratorHelper(output, posIter, appendTo.length(), status);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, status);
    return appendTo;
}

UnicodeString&
DecimalFormat::format(const DecimalQuantity& number, UnicodeString& appendTo, FieldPosition& pos,
                      UErrorCode& status) const {
    if (U_FAILURE(status)) {
        return appendTo; // don't overwrite status if it's already a failure.
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        appendTo.setToBogus();
        return appendTo;
    }
    FormattedNumber output = fields->formatter->formatDecimalQuantity(number, status);
    fieldPositionHelper(output, pos, appendTo.length(), status);
    auto appendable = UnicodeStringAppendable(appendTo);
    output.appendTo(appendable, status);
    return appendTo;
}

void DecimalFormat::parse(const UnicodeString& text, Formattable& output,
                          ParsePosition& parsePosition) const {
    if (fields == nullptr) {
        return;
    }
    if (parsePosition.getIndex() < 0 || parsePosition.getIndex() >= text.length()) {
        if (parsePosition.getIndex() == text.length()) {
            // If there is nothing to parse, it is an error
            parsePosition.setErrorIndex(parsePosition.getIndex());
        }
        return;
    }

    ErrorCode status;
    ParsedNumber result;
    // Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the
    // parseCurrency method (backwards compatibility)
    int32_t startIndex = parsePosition.getIndex();
    const NumberParserImpl* parser = getParser(status);
    if (U_FAILURE(status)) {
        return; // unfortunately no way to report back the error.
    }
    parser->parse(text, startIndex, true, result, status);
    if (U_FAILURE(status)) {
        return; // unfortunately no way to report back the error.
    }
    // TODO: Do we need to check for fImpl->properties->parseAllInput (UCONFIG_HAVE_PARSEALLINPUT) here?
    if (result.success()) {
        parsePosition.setIndex(result.charEnd);
        result.populateFormattable(output, parser->getParseFlags());
    } else {
        parsePosition.setErrorIndex(startIndex + result.charEnd);
    }
}

CurrencyAmount* DecimalFormat::parseCurrency(const UnicodeString& text, ParsePosition& parsePosition) const {
    if (fields == nullptr) {
        return nullptr;
    }
    if (parsePosition.getIndex() < 0 || parsePosition.getIndex() >= text.length()) {
        return nullptr;
    }

    ErrorCode status;
    ParsedNumber result;
    // Note: if this is a currency instance, currencies will be matched despite the fact that we are not in the
    // parseCurrency method (backwards compatibility)
    int32_t startIndex = parsePosition.getIndex();
    const NumberParserImpl* parser = getCurrencyParser(status);
    if (U_FAILURE(status)) {
        return nullptr;
    }
    parser->parse(text, startIndex, true, result, status);
    if (U_FAILURE(status)) {
        return nullptr;
    }
    // TODO: Do we need to check for fImpl->properties->parseAllInput (UCONFIG_HAVE_PARSEALLINPUT) here?
    if (result.success()) {
        parsePosition.setIndex(result.charEnd);
        Formattable formattable;
        result.populateFormattable(formattable, parser->getParseFlags());
        LocalPointer<CurrencyAmount> currencyAmount(
            new CurrencyAmount(formattable, result.currencyCode, status), status);
        if (U_FAILURE(status)) {
            return nullptr;
        }
        return currencyAmount.orphan();
    } else {
        parsePosition.setErrorIndex(startIndex + result.charEnd);
        return nullptr;
    }
}

const DecimalFormatSymbols* DecimalFormat::getDecimalFormatSymbols(void) const {
    if (fields == nullptr) {
        return nullptr;
    }
    return fields->symbols.getAlias();
}

void DecimalFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt) {
    if (symbolsToAdopt == nullptr) {
        return; // do not allow caller to set fields->symbols to NULL
    }
    // we must take ownership of symbolsToAdopt, even in a failure case.
    LocalPointer<DecimalFormatSymbols> dfs(symbolsToAdopt);
    if (fields == nullptr) {
        return;
    }
    fields->symbols.adoptInstead(dfs.orphan());
    touchNoError();
}

void DecimalFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols) {
    if (fields == nullptr) {
        return;
    }
    UErrorCode status = U_ZERO_ERROR;
    LocalPointer<DecimalFormatSymbols> dfs(new DecimalFormatSymbols(symbols), status);
    if (U_FAILURE(status)) {
        // We failed to allocate DecimalFormatSymbols, release fields and its members.
        // We must have a fully complete fields object, we cannot have partially populated members.
        delete fields;
        fields = nullptr;
        return;
    }
    fields->symbols.adoptInstead(dfs.orphan());
    touchNoError();
}

const CurrencyPluralInfo* DecimalFormat::getCurrencyPluralInfo(void) const {
    if (fields == nullptr) {
        return nullptr;
    }
    return fields->properties->currencyPluralInfo.fPtr.getAlias();
}

void DecimalFormat::adoptCurrencyPluralInfo(CurrencyPluralInfo* toAdopt) {
    // TODO: should we guard against nullptr input, like in adoptDecimalFormatSymbols?
    // we must take ownership of toAdopt, even in a failure case.
    LocalPointer<CurrencyPluralInfo> cpi(toAdopt);
    if (fields == nullptr) {
        return;
    }
    fields->properties->currencyPluralInfo.fPtr.adoptInstead(cpi.orphan());
    touchNoError();
}

void DecimalFormat::setCurrencyPluralInfo(const CurrencyPluralInfo& info) {
    if (fields == nullptr) {
        return;
    }
    if (fields->properties->currencyPluralInfo.fPtr.isNull()) {
        // Note: clone() can fail with OOM error, but we have no way to report it. :(
        fields->properties->currencyPluralInfo.fPtr.adoptInstead(info.clone());
    } else {
        *fields->properties->currencyPluralInfo.fPtr = info; // copy-assignment operator
    }
    touchNoError();
}

UnicodeString& DecimalFormat::getPositivePrefix(UnicodeString& result) const {
    if (fields == nullptr) {
        result.setToBogus();
        return result;
    }
    UErrorCode status = U_ZERO_ERROR;
    fields->formatter->getAffixImpl(true, false, result, status);
    if (U_FAILURE(status)) { result.setToBogus(); }
    return result;
}

void DecimalFormat::setPositivePrefix(const UnicodeString& newValue) {
    if (fields == nullptr) {
        return;
    }
    if (newValue == fields->properties->positivePrefix) { return; }
    fields->properties->positivePrefix = newValue;
    touchNoError();
}

UnicodeString& DecimalFormat::getNegativePrefix(UnicodeString& result) const {
    if (fields == nullptr) {
        result.setToBogus();
        return result;
    }
    UErrorCode status = U_ZERO_ERROR;
    fields->formatter->getAffixImpl(true, true, result, status);
    if (U_FAILURE(status)) { result.setToBogus(); }
    return result;
}

void DecimalFormat::setNegativePrefix(const UnicodeString& newValue) {
    if (fields == nullptr) {
        return;
    }
    if (newValue == fields->properties->negativePrefix) { return; }
    fields->properties->negativePrefix = newValue;
    touchNoError();
}

UnicodeString& DecimalFormat::getPositiveSuffix(UnicodeString& result) const {
    if (fields == nullptr) {
        result.setToBogus();
        return result;
    }
    UErrorCode status = U_ZERO_ERROR;
    fields->formatter->getAffixImpl(false, false, result, status);
    if (U_FAILURE(status)) { result.setToBogus(); }
    return result;
}

void DecimalFormat::setPositiveSuffix(const UnicodeString& newValue) {
    if (fields == nullptr) {
        return;
    }
    if (newValue == fields->properties->positiveSuffix) { return; }
    fields->properties->positiveSuffix = newValue;
    touchNoError();
}

UnicodeString& DecimalFormat::getNegativeSuffix(UnicodeString& result) const {
    if (fields == nullptr) {
        result.setToBogus();
        return result;
    }
    UErrorCode status = U_ZERO_ERROR;
    fields->formatter->getAffixImpl(false, true, result, status);
    if (U_FAILURE(status)) { result.setToBogus(); }
    return result;
}

void DecimalFormat::setNegativeSuffix(const UnicodeString& newValue) {
    if (fields == nullptr) {
        return;
    }
    if (newValue == fields->properties->negativeSuffix) { return; }
    fields->properties->negativeSuffix = newValue;
    touchNoError();
}

UBool DecimalFormat::isSignAlwaysShown() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        return DecimalFormatProperties::getDefault().signAlwaysShown;
    }
    return fields->properties->signAlwaysShown;
}

void DecimalFormat::setSignAlwaysShown(UBool value) {
    if (fields == nullptr) { return; }
    if (UBOOL_TO_BOOL(value) == fields->properties->signAlwaysShown) { return; }
    fields->properties->signAlwaysShown = value;
    touchNoError();
}

int32_t DecimalFormat::getMultiplier(void) const {
    const DecimalFormatProperties *dfp;
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        dfp = &(DecimalFormatProperties::getDefault());
    } else {
        dfp = fields->properties.getAlias();
    }
    if (dfp->multiplier != 1) {
        return dfp->multiplier;
    } else if (dfp->magnitudeMultiplier != 0) {
        return static_cast<int32_t>(uprv_pow10(dfp->magnitudeMultiplier));
    } else {
        return 1;
    }
}

void DecimalFormat::setMultiplier(int32_t multiplier) {
    if (fields == nullptr) {
         return;
    }
    if (multiplier == 0) {
        multiplier = 1;     // one being the benign default value for a multiplier.
    }

    // Try to convert to a magnitude multiplier first
    int delta = 0;
    int value = multiplier;
    while (value != 1) {
        delta++;
        int temp = value / 10;
        if (temp * 10 != value) {
            delta = -1;
            break;
        }
        value = temp;
    }
    if (delta != -1) {
        fields->properties->magnitudeMultiplier = delta;
        fields->properties->multiplier = 1;
    } else {
        fields->properties->magnitudeMultiplier = 0;
        fields->properties->multiplier = multiplier;
    }
    touchNoError();
}

int32_t DecimalFormat::getMultiplierScale() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().multiplierScale;
    }
    return fields->properties->multiplierScale;
}

void DecimalFormat::setMultiplierScale(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->multiplierScale) { return; }
    fields->properties->multiplierScale = newValue;
    touchNoError();
}

double DecimalFormat::getRoundingIncrement(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().roundingIncrement;
    }
    return fields->exportedProperties->roundingIncrement;
}

void DecimalFormat::setRoundingIncrement(double newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->roundingIncrement) { return; }
    fields->properties->roundingIncrement = newValue;
    touchNoError();
}

ERoundingMode DecimalFormat::getRoundingMode(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return static_cast<ERoundingMode>(DecimalFormatProperties::getDefault().roundingMode.getNoError());
    }
    // UNumberFormatRoundingMode and ERoundingMode have the same values.
    return static_cast<ERoundingMode>(fields->exportedProperties->roundingMode.getNoError());
}

void DecimalFormat::setRoundingMode(ERoundingMode roundingMode) {
    if (fields == nullptr) { return; }
    auto uRoundingMode = static_cast<UNumberFormatRoundingMode>(roundingMode);
    if (!fields->properties->roundingMode.isNull() && uRoundingMode == fields->properties->roundingMode.getNoError()) {
        return;
    }
    NumberFormat::setMaximumIntegerDigits(roundingMode); // to set field for compatibility
    fields->properties->roundingMode = uRoundingMode;
    touchNoError();
}

int32_t DecimalFormat::getFormatWidth(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().formatWidth;
    }
    return fields->properties->formatWidth;
}

void DecimalFormat::setFormatWidth(int32_t width) {
    if (fields == nullptr) { return; }
    if (width == fields->properties->formatWidth) { return; }
    fields->properties->formatWidth = width;
    touchNoError();
}

UnicodeString DecimalFormat::getPadCharacterString() const {
    if (fields == nullptr || fields->properties->padString.isBogus()) {
        // Readonly-alias the static string kFallbackPaddingString
        return {TRUE, kFallbackPaddingString, -1};
    } else {
        return fields->properties->padString;
    }
}

void DecimalFormat::setPadCharacter(const UnicodeString& padChar) {
    if (fields == nullptr) { return; }
    if (padChar == fields->properties->padString) { return; }
    if (padChar.length() > 0) {
        fields->properties->padString = UnicodeString(padChar.char32At(0));
    } else {
        fields->properties->padString.setToBogus();
    }
    touchNoError();
}

EPadPosition DecimalFormat::getPadPosition(void) const {
    if (fields == nullptr || fields->properties->padPosition.isNull()) {
        return EPadPosition::kPadBeforePrefix;
    } else {
        // UNumberFormatPadPosition and EPadPosition have the same values.
        return static_cast<EPadPosition>(fields->properties->padPosition.getNoError());
    }
}

void DecimalFormat::setPadPosition(EPadPosition padPos) {
    if (fields == nullptr) { return; }
    auto uPadPos = static_cast<UNumberFormatPadPosition>(padPos);
    if (!fields->properties->padPosition.isNull() && uPadPos == fields->properties->padPosition.getNoError()) {
        return;
    }
    fields->properties->padPosition = uPadPos;
    touchNoError();
}

UBool DecimalFormat::isScientificNotation(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return (DecimalFormatProperties::getDefault().minimumExponentDigits != -1);
    }
    return (fields->properties->minimumExponentDigits != -1);
}

void DecimalFormat::setScientificNotation(UBool useScientific) {
    if (fields == nullptr) { return; }
    int32_t minExp = useScientific ? 1 : -1;
    if (fields->properties->minimumExponentDigits == minExp) { return; }
    if (useScientific) {
        fields->properties->minimumExponentDigits = 1;
    } else {
        fields->properties->minimumExponentDigits = -1;
    }
    touchNoError();
}

int8_t DecimalFormat::getMinimumExponentDigits(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return static_cast<int8_t>(DecimalFormatProperties::getDefault().minimumExponentDigits);
    }
    return static_cast<int8_t>(fields->properties->minimumExponentDigits);
}

void DecimalFormat::setMinimumExponentDigits(int8_t minExpDig) {
    if (fields == nullptr) { return; }
    if (minExpDig == fields->properties->minimumExponentDigits) { return; }
    fields->properties->minimumExponentDigits = minExpDig;
    touchNoError();
}

UBool DecimalFormat::isExponentSignAlwaysShown(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().exponentSignAlwaysShown;
    }
    return fields->properties->exponentSignAlwaysShown;
}

void DecimalFormat::setExponentSignAlwaysShown(UBool expSignAlways) {
    if (fields == nullptr) { return; }
    if (UBOOL_TO_BOOL(expSignAlways) == fields->properties->exponentSignAlwaysShown) { return; }
    fields->properties->exponentSignAlwaysShown = expSignAlways;
    touchNoError();
}

int32_t DecimalFormat::getGroupingSize(void) const {
    int32_t groupingSize;
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        groupingSize = DecimalFormatProperties::getDefault().groupingSize;
    } else {
        groupingSize = fields->properties->groupingSize;
    }
    if (groupingSize < 0) {
        return 0;
    }
    return groupingSize;
}

void DecimalFormat::setGroupingSize(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->groupingSize) { return; }
    fields->properties->groupingSize = newValue;
    touchNoError();
}

int32_t DecimalFormat::getSecondaryGroupingSize(void) const {
    int32_t grouping2;
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        grouping2 = DecimalFormatProperties::getDefault().secondaryGroupingSize;
    } else {
        grouping2 = fields->properties->secondaryGroupingSize;
    }
    if (grouping2 < 0) {
        return 0;
    }
    return grouping2;
}

void DecimalFormat::setSecondaryGroupingSize(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->secondaryGroupingSize) { return; }
    fields->properties->secondaryGroupingSize = newValue;
    touchNoError();
}

int32_t DecimalFormat::getMinimumGroupingDigits() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().minimumGroupingDigits;
    }
    return fields->properties->minimumGroupingDigits;
}

void DecimalFormat::setMinimumGroupingDigits(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->minimumGroupingDigits) { return; }
    fields->properties->minimumGroupingDigits = newValue;
    touchNoError();
}

UBool DecimalFormat::isDecimalSeparatorAlwaysShown(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().decimalSeparatorAlwaysShown;
    }
    return fields->properties->decimalSeparatorAlwaysShown;
}

void DecimalFormat::setDecimalSeparatorAlwaysShown(UBool newValue) {
    if (fields == nullptr) { return; }
    if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalSeparatorAlwaysShown) { return; }
    fields->properties->decimalSeparatorAlwaysShown = newValue;
    touchNoError();
}

UBool DecimalFormat::isDecimalPatternMatchRequired(void) const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().decimalPatternMatchRequired;
    }
    return fields->properties->decimalPatternMatchRequired;
}

void DecimalFormat::setDecimalPatternMatchRequired(UBool newValue) {
    if (fields == nullptr) { return; }
    if (UBOOL_TO_BOOL(newValue) == fields->properties->decimalPatternMatchRequired) { return; }
    fields->properties->decimalPatternMatchRequired = newValue;
    touchNoError();
}

UBool DecimalFormat::isParseNoExponent() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().parseNoExponent;
    }
    return fields->properties->parseNoExponent;
}

void DecimalFormat::setParseNoExponent(UBool value) {
    if (fields == nullptr) { return; }
    if (UBOOL_TO_BOOL(value) == fields->properties->parseNoExponent) { return; }
    fields->properties->parseNoExponent = value;
    touchNoError();
}

UBool DecimalFormat::isParseCaseSensitive() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().parseCaseSensitive;
    }
    return fields->properties->parseCaseSensitive;
}

void DecimalFormat::setParseCaseSensitive(UBool value) {
    if (fields == nullptr) { return; }
    if (UBOOL_TO_BOOL(value) == fields->properties->parseCaseSensitive) { return; }
    fields->properties->parseCaseSensitive = value;
    touchNoError();
}

UBool DecimalFormat::isFormatFailIfMoreThanMaxDigits() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().formatFailIfMoreThanMaxDigits;
    }
    return fields->properties->formatFailIfMoreThanMaxDigits;
}

void DecimalFormat::setFormatFailIfMoreThanMaxDigits(UBool value) {
    if (fields == nullptr) { return; }
    if (UBOOL_TO_BOOL(value) == fields->properties->formatFailIfMoreThanMaxDigits) { return; }
    fields->properties->formatFailIfMoreThanMaxDigits = value;
    touchNoError();
}

UnicodeString& DecimalFormat::toPattern(UnicodeString& result) const {
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        result.setToBogus();
        return result;
    }
    // Pull some properties from exportedProperties and others from properties
    // to keep affix patterns intact.  In particular, pull rounding properties
    // so that CurrencyUsage is reflected properly.
    // TODO: Consider putting this logic in number_patternstring.cpp instead.
    ErrorCode localStatus;
    DecimalFormatProperties tprops(*fields->properties);
    bool useCurrency = (
        !tprops.currency.isNull() ||
        !tprops.currencyPluralInfo.fPtr.isNull() ||
        !tprops.currencyUsage.isNull() ||
        AffixUtils::hasCurrencySymbols(tprops.positivePrefixPattern, localStatus) ||
        AffixUtils::hasCurrencySymbols(tprops.positiveSuffixPattern, localStatus) ||
        AffixUtils::hasCurrencySymbols(tprops.negativePrefixPattern, localStatus) ||
        AffixUtils::hasCurrencySymbols(tprops.negativeSuffixPattern, localStatus));
    if (useCurrency) {
        tprops.minimumFractionDigits = fields->exportedProperties->minimumFractionDigits;
        tprops.maximumFractionDigits = fields->exportedProperties->maximumFractionDigits;
        tprops.roundingIncrement = fields->exportedProperties->roundingIncrement;
    }
    result = PatternStringUtils::propertiesToPatternString(tprops, localStatus);
    return result;
}

UnicodeString& DecimalFormat::toLocalizedPattern(UnicodeString& result) const {
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        result.setToBogus();
        return result;
    }
    ErrorCode localStatus;
    result = toPattern(result);
    result = PatternStringUtils::convertLocalized(result, *fields->symbols, true, localStatus);
    return result;
}

void DecimalFormat::applyPattern(const UnicodeString& pattern, UParseError&, UErrorCode& status) {
    // TODO: What is parseError for?
    applyPattern(pattern, status);
}

void DecimalFormat::applyPattern(const UnicodeString& pattern, UErrorCode& status) {
    // don't overwrite status if it's already a failure.
    if (U_FAILURE(status)) { return; }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    setPropertiesFromPattern(pattern, IGNORE_ROUNDING_NEVER, status);
    touch(status);
}

void DecimalFormat::applyLocalizedPattern(const UnicodeString& localizedPattern, UParseError&,
                                          UErrorCode& status) {
    // TODO: What is parseError for?
    applyLocalizedPattern(localizedPattern, status);
}

void DecimalFormat::applyLocalizedPattern(const UnicodeString& localizedPattern, UErrorCode& status) {
    // don't overwrite status if it's already a failure.
    if (U_FAILURE(status)) { return; }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    UnicodeString pattern = PatternStringUtils::convertLocalized(
            localizedPattern, *fields->symbols, false, status);
    applyPattern(pattern, status);
}

void DecimalFormat::setMaximumIntegerDigits(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->maximumIntegerDigits) { return; }
    // For backwards compatibility, conflicting min/max need to keep the most recent setting.
    int32_t min = fields->properties->minimumIntegerDigits;
    if (min >= 0 && min > newValue) {
        fields->properties->minimumIntegerDigits = newValue;
    }
    fields->properties->maximumIntegerDigits = newValue;
    touchNoError();
}

void DecimalFormat::setMinimumIntegerDigits(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->minimumIntegerDigits) { return; }
    // For backwards compatibility, conflicting min/max need to keep the most recent setting.
    int32_t max = fields->properties->maximumIntegerDigits;
    if (max >= 0 && max < newValue) {
        fields->properties->maximumIntegerDigits = newValue;
    }
    fields->properties->minimumIntegerDigits = newValue;
    touchNoError();
}

void DecimalFormat::setMaximumFractionDigits(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->maximumFractionDigits) { return; }
    // For backwards compatibility, conflicting min/max need to keep the most recent setting.
    int32_t min = fields->properties->minimumFractionDigits;
    if (min >= 0 && min > newValue) {
        fields->properties->minimumFractionDigits = newValue;
    }
    fields->properties->maximumFractionDigits = newValue;
    touchNoError();
}

void DecimalFormat::setMinimumFractionDigits(int32_t newValue) {
    if (fields == nullptr) { return; }
    if (newValue == fields->properties->minimumFractionDigits) { return; }
    // For backwards compatibility, conflicting min/max need to keep the most recent setting.
    int32_t max = fields->properties->maximumFractionDigits;
    if (max >= 0 && max < newValue) {
        fields->properties->maximumFractionDigits = newValue;
    }
    fields->properties->minimumFractionDigits = newValue;
    touchNoError();
}

int32_t DecimalFormat::getMinimumSignificantDigits() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().minimumSignificantDigits;
    }
    return fields->exportedProperties->minimumSignificantDigits;
}

int32_t DecimalFormat::getMaximumSignificantDigits() const {
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        return DecimalFormatProperties::getDefault().maximumSignificantDigits;
    }
    return fields->exportedProperties->maximumSignificantDigits;
}

void DecimalFormat::setMinimumSignificantDigits(int32_t value) {
    if (fields == nullptr) { return; }
    if (value == fields->properties->minimumSignificantDigits) { return; }
    int32_t max = fields->properties->maximumSignificantDigits;
    if (max >= 0 && max < value) {
        fields->properties->maximumSignificantDigits = value;
    }
    fields->properties->minimumSignificantDigits = value;
    touchNoError();
}

void DecimalFormat::setMaximumSignificantDigits(int32_t value) {
    if (fields == nullptr) { return; }
    if (value == fields->properties->maximumSignificantDigits) { return; }
    int32_t min = fields->properties->minimumSignificantDigits;
    if (min >= 0 && min > value) {
        fields->properties->minimumSignificantDigits = value;
    }
    fields->properties->maximumSignificantDigits = value;
    touchNoError();
}

UBool DecimalFormat::areSignificantDigitsUsed() const {
    const DecimalFormatProperties* dfp;
    // Not much we can do to report an error.
    if (fields == nullptr) {
        // Fallback to using the default instance of DecimalFormatProperties.
        dfp = &(DecimalFormatProperties::getDefault());
    } else {
        dfp = fields->properties.getAlias();
    }
    return dfp->minimumSignificantDigits != -1 || dfp->maximumSignificantDigits != -1;    
}

void DecimalFormat::setSignificantDigitsUsed(UBool useSignificantDigits) {
    if (fields == nullptr) { return; }
    
    // These are the default values from the old implementation.
    if (useSignificantDigits) {
        if (fields->properties->minimumSignificantDigits != -1 ||
            fields->properties->maximumSignificantDigits != -1) {
            return;
        }
    } else {
        if (fields->properties->minimumSignificantDigits == -1 &&
            fields->properties->maximumSignificantDigits == -1) {
            return;
        }
    }
    int32_t minSig = useSignificantDigits ? 1 : -1;
    int32_t maxSig = useSignificantDigits ? 6 : -1;
    fields->properties->minimumSignificantDigits = minSig;
    fields->properties->maximumSignificantDigits = maxSig;
    touchNoError();
}

void DecimalFormat::setCurrency(const char16_t* theCurrency, UErrorCode& ec) {
    // don't overwrite ec if it's already a failure.
    if (U_FAILURE(ec)) { return; }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        ec = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    CurrencyUnit currencyUnit(theCurrency, ec);
    if (U_FAILURE(ec)) { return; }
    if (!fields->properties->currency.isNull() && fields->properties->currency.getNoError() == currencyUnit) {
        return;
    }
    NumberFormat::setCurrency(theCurrency, ec); // to set field for compatibility
    fields->properties->currency = currencyUnit;
    // TODO: Set values in fields->symbols, too?
    touchNoError();
}

void DecimalFormat::setCurrency(const char16_t* theCurrency) {
    ErrorCode localStatus;
    setCurrency(theCurrency, localStatus);
}

void DecimalFormat::setCurrencyUsage(UCurrencyUsage newUsage, UErrorCode* ec) {
    // don't overwrite ec if it's already a failure.
    if (U_FAILURE(*ec)) { return; }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        *ec = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    if (!fields->properties->currencyUsage.isNull() && newUsage == fields->properties->currencyUsage.getNoError()) {
        return;
    }
    fields->properties->currencyUsage = newUsage;
    touch(*ec);
}

UCurrencyUsage DecimalFormat::getCurrencyUsage() const {
    // CurrencyUsage is not exported, so we have to get it from the input property bag.
    // TODO: Should we export CurrencyUsage instead?
    if (fields == nullptr || fields->properties->currencyUsage.isNull()) {
        return UCURR_USAGE_STANDARD;
    }
    return fields->properties->currencyUsage.getNoError();
}

void
DecimalFormat::formatToDecimalQuantity(double number, DecimalQuantity& output, UErrorCode& status) const {
    // don't overwrite status if it's already a failure.
    if (U_FAILURE(status)) { return; }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    fields->formatter->formatDouble(number, status).getDecimalQuantity(output, status);
}

void DecimalFormat::formatToDecimalQuantity(const Formattable& number, DecimalQuantity& output,
                                            UErrorCode& status) const {
    // don't overwrite status if it's already a failure.
    if (U_FAILURE(status)) { return; }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }
    UFormattedNumberData obj;
    number.populateDecimalQuantity(obj.quantity, status);
    fields->formatter->formatImpl(&obj, status);
    output = std::move(obj.quantity);
}

const number::LocalizedNumberFormatter& DecimalFormat::toNumberFormatter() const {
    // TODO: See ICU-20366 and ICU-20380. Currently there isn't really any good way to report an error here.
    if (fields != nullptr) {
        return *fields->formatter;
    }
    // The code below is undefined behavior and may crash anyways, but we don't really have any choice since
    // this method returns a reference.
    // TODO: Should we have a static-allocated LocalizedNumberFormatter (in a failed state) somewhere so that
    // it could be used here?
    number::LocalizedNumberFormatter *bad = nullptr;
    return static_cast<const number::LocalizedNumberFormatter &>(*bad);
}

/** Rebuilds the formatter object from the property bag. */
void DecimalFormat::touch(UErrorCode& status) {
    if (U_FAILURE(status)) {
        return;
    }
    if (fields == nullptr) {
        // We only get here if an OOM error happend during construction, copy construction, assignment, or modification.
        // For regular construction, the caller should have checked the status variable for errors.
        // For copy construction, there is unfortunately nothing to report the error, so we need to guard against
        // this possible bad state here and set the status to an error.
        status = U_MEMORY_ALLOCATION_ERROR;
        return;
    }

    // In C++, fields->symbols is the source of truth for the locale.
    Locale locale = fields->symbols->getLocale();

    // Note: The formatter is relatively cheap to create, and we need it to populate fields->exportedProperties,
    // so automatically recompute it here. The parser is a bit more expensive and is not needed until the
    // parse method is called, so defer that until needed.
    // TODO: Only update the pieces that changed instead of re-computing the whole formatter?
 
    // Since memory has already been allocated for the formatter, we can move assign a stack-allocated object
    // and don't need to call new. (Which is slower and could possibly fail).
    *fields->formatter = NumberPropertyMapper::create(
        *fields->properties, *fields->symbols, fields->warehouse, *fields->exportedProperties, status).locale(
            locale);

    // Do this after fields->exportedProperties are set up
    setupFastFormat();

    // Delete the parsers if they were made previously
    delete fields->atomicParser.exchange(nullptr);
    delete fields->atomicCurrencyParser.exchange(nullptr);

    // In order for the getters to work, we need to populate some fields in NumberFormat.
    NumberFormat::setCurrency(fields->exportedProperties->currency.get(status).getISOCurrency(), status);
    NumberFormat::setMaximumIntegerDigits(fields->exportedProperties->maximumIntegerDigits);
    NumberFormat::setMinimumIntegerDigits(fields->exportedProperties->minimumIntegerDigits);
    NumberFormat::setMaximumFractionDigits(fields->exportedProperties->maximumFractionDigits);
    NumberFormat::setMinimumFractionDigits(fields->exportedProperties->minimumFractionDigits);
    // fImpl->properties, not fields->exportedProperties, since this information comes from the pattern:
    NumberFormat::setGroupingUsed(fields->properties->groupingUsed);
}

void DecimalFormat::touchNoError() {
    UErrorCode localStatus = U_ZERO_ERROR;
    touch(localStatus);
}

void DecimalFormat::setPropertiesFromPattern(const UnicodeString& pattern, int32_t ignoreRounding,
                                             UErrorCode& status) {
    if (U_SUCCESS(status)) {
        // Cast workaround to get around putting the enum in the public header file
        auto actualIgnoreRounding = static_cast<IgnoreRounding>(ignoreRounding);
        PatternParser::parseToExistingProperties(pattern, *fields->properties,  actualIgnoreRounding, status);
    }
}

const numparse::impl::NumberParserImpl* DecimalFormat::getParser(UErrorCode& status) const {
    // TODO: Move this into umutex.h? (similar logic also in numrange_fluent.cpp)
    // See ICU-20146

    if (U_FAILURE(status)) {
        return nullptr;
    }

    // First try to get the pre-computed parser
    auto* ptr = fields->atomicParser.load();
    if (ptr != nullptr) {
        return ptr;
    }

    // Try computing the parser on our own
    auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, false, status);
    if (U_FAILURE(status)) {
        return nullptr;
    }
    if (temp == nullptr) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return nullptr;
    }

    // Note: ptr starts as nullptr; during compare_exchange,
    // it is set to what is actually stored in the atomic
    // if another thread beat us to computing the parser object.
    auto* nonConstThis = const_cast<DecimalFormat*>(this);
    if (!nonConstThis->fields->atomicParser.compare_exchange_strong(ptr, temp)) {
        // Another thread beat us to computing the parser
        delete temp;
        return ptr;
    } else {
        // Our copy of the parser got stored in the atomic
        return temp;
    }
}

const numparse::impl::NumberParserImpl* DecimalFormat::getCurrencyParser(UErrorCode& status) const {
    if (U_FAILURE(status)) { return nullptr; }

    // First try to get the pre-computed parser
    auto* ptr = fields->atomicCurrencyParser.load();
    if (ptr != nullptr) {
        return ptr;
    }

    // Try computing the parser on our own
    auto* temp = NumberParserImpl::createParserFromProperties(*fields->properties, *fields->symbols, true, status);
    if (temp == nullptr) {
        status = U_MEMORY_ALLOCATION_ERROR;
        // although we may still dereference, call sites should be guarded
    }

    // Note: ptr starts as nullptr; during compare_exchange, it is set to what is actually stored in the
    // atomic if another thread beat us to computing the parser object.
    auto* nonConstThis = const_cast<DecimalFormat*>(this);
    if (!nonConstThis->fields->atomicCurrencyParser.compare_exchange_strong(ptr, temp)) {
        // Another thread beat us to computing the parser
        delete temp;
        return ptr;
    } else {
        // Our copy of the parser got stored in the atomic
        return temp;
    }
}

void
DecimalFormat::fieldPositionHelper(const number::FormattedNumber& formatted, FieldPosition& fieldPosition,
                                   int32_t offset, UErrorCode& status) {
    if (U_FAILURE(status)) { return; }
    // always return first occurrence:
    fieldPosition.setBeginIndex(0);
    fieldPosition.setEndIndex(0);
    bool found = formatted.nextFieldPosition(fieldPosition, status);
    if (found && offset != 0) {
        FieldPositionOnlyHandler fpoh(fieldPosition);
        fpoh.shiftLast(offset);
    }
}

void
DecimalFormat::fieldPositionIteratorHelper(const number::FormattedNumber& formatted, FieldPositionIterator* fpi,
                                           int32_t offset, UErrorCode& status) {
    if (U_SUCCESS(status) && (fpi != nullptr)) {
        FieldPositionIteratorHandler fpih(fpi, status);
        fpih.setShift(offset);
        formatted.getAllFieldPositionsImpl(fpih, status);
    }
}

// To debug fast-format, change void(x) to printf(x)
#define trace(x) void(x)

void DecimalFormat::setupFastFormat() {
    // Check the majority of properties:
    if (!fields->properties->equalsDefaultExceptFastFormat()) {
        trace("no fast format: equality\n");
        fields->canUseFastFormat = false;
        return;
    }

    // Now check the remaining properties.
    // Nontrivial affixes:
    UBool trivialPP = fields->properties->positivePrefixPattern.isEmpty();
    UBool trivialPS = fields->properties->positiveSuffixPattern.isEmpty();
    UBool trivialNP = fields->properties->negativePrefixPattern.isBogus() || (
            fields->properties->negativePrefixPattern.length() == 1 &&
            fields->properties->negativePrefixPattern.charAt(0) == u'-');
    UBool trivialNS = fields->properties->negativeSuffixPattern.isEmpty();
    if (!trivialPP || !trivialPS || !trivialNP || !trivialNS) {
        trace("no fast format: affixes\n");
        fields->canUseFastFormat = false;
        return;
    }

    // Grouping (secondary grouping is forbidden in equalsDefaultExceptFastFormat):
    bool groupingUsed = fields->properties->groupingUsed;
    int32_t groupingSize = fields->properties->groupingSize;
    bool unusualGroupingSize = groupingSize > 0 && groupingSize != 3;
    const UnicodeString& groupingString = fields->symbols->getConstSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol);
    if (groupingUsed && (unusualGroupingSize || groupingString.length() != 1)) {
        trace("no fast format: grouping\n");
        fields->canUseFastFormat = false;
        return;
    }

    // Integer length:
    int32_t minInt = fields->exportedProperties->minimumIntegerDigits;
    int32_t maxInt = fields->exportedProperties->maximumIntegerDigits;
    // Fastpath supports up to only 10 digits (length of INT32_MIN)
    if (minInt > 10) {
        trace("no fast format: integer\n");
        fields->canUseFastFormat = false;
        return;
    }

    // Fraction length (no fraction part allowed in fast path):
    int32_t minFrac = fields->exportedProperties->minimumFractionDigits;
    if (minFrac > 0) {
        trace("no fast format: fraction\n");
        fields->canUseFastFormat = false;
        return;
    }

    // Other symbols:
    const UnicodeString& minusSignString = fields->symbols->getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
    UChar32 codePointZero = fields->symbols->getCodePointZero();
    if (minusSignString.length() != 1 || U16_LENGTH(codePointZero) != 1) {
        trace("no fast format: symbols\n");
        fields->canUseFastFormat = false;
        return;
    }

    // Good to go!
    trace("can use fast format!\n");
    fields->canUseFastFormat = true;
    fields->fastData.cpZero = static_cast<char16_t>(codePointZero);
    fields->fastData.cpGroupingSeparator = groupingUsed && groupingSize == 3 ? groupingString.charAt(0) : 0;
    fields->fastData.cpMinusSign = minusSignString.charAt(0);
    fields->fastData.minInt = (minInt < 0 || minInt > 127) ? 0 : static_cast<int8_t>(minInt);
    fields->fastData.maxInt = (maxInt < 0 || maxInt > 127) ? 127 : static_cast<int8_t>(maxInt);
}

bool DecimalFormat::fastFormatDouble(double input, UnicodeString& output) const {
    if (!fields->canUseFastFormat) {
        return false;
    }
    if (std::isnan(input)
            || std::trunc(input) != input
            || input <= INT32_MIN
            || input > INT32_MAX) {
        return false;
    }
    doFastFormatInt32(static_cast<int32_t>(input), std::signbit(input), output);
    return true;
}

bool DecimalFormat::fastFormatInt64(int64_t input, UnicodeString& output) const {
    if (!fields->canUseFastFormat) {
        return false;
    }
    if (input <= INT32_MIN || input > INT32_MAX) {
        return false;
    }
    doFastFormatInt32(static_cast<int32_t>(input), input < 0, output);
    return true;
}

void DecimalFormat::doFastFormatInt32(int32_t input, bool isNegative, UnicodeString& output) const {
    U_ASSERT(fields->canUseFastFormat);
    if (isNegative) {
        output.append(fields->fastData.cpMinusSign);
        U_ASSERT(input != INT32_MIN);  // handled by callers
        input = -input;
    }
    // Cap at int32_t to make the buffer small and operations fast.
    // Longest string: "2,147,483,648" (13 chars in length)
    static constexpr int32_t localCapacity = 13;
    char16_t localBuffer[localCapacity];
    char16_t* ptr = localBuffer + localCapacity;
    int8_t group = 0;
    for (int8_t i = 0; i < fields->fastData.maxInt && (input != 0 || i < fields->fastData.minInt); i++) {
        if (group++ == 3 && fields->fastData.cpGroupingSeparator != 0) {
            *(--ptr) = fields->fastData.cpGroupingSeparator;
            group = 1;
        }
        std::div_t res = std::div(input, 10);
        *(--ptr) = static_cast<char16_t>(fields->fastData.cpZero + res.rem);
        input = res.quot;
    }
    int32_t len = localCapacity - static_cast<int32_t>(ptr - localBuffer);
    output.append(ptr, len);
}


#endif /* #if !UCONFIG_NO_FORMATTING */
