// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 1997-2016, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
* File DCFMTSYM.CPP
*
* Modification History:
*
*   Date        Name        Description
*   02/19/97    aliu        Converted from java.
*   03/18/97    clhuang     Implemented with C++ APIs.
*   03/27/97    helena      Updated to pass the simple test after code review.
*   08/26/97    aliu        Added currency/intl currency symbol support.
*   07/20/98    stephen     Slightly modified initialization of monetarySeparator
********************************************************************************
*/

#include "unicode/utypes.h"

#if !UCONFIG_NO_FORMATTING

#include "unicode/dcfmtsym.h"
#include "unicode/ures.h"
#include "unicode/decimfmt.h"
#include "unicode/ucurr.h"
#include "unicode/choicfmt.h"
#include "unicode/unistr.h"
#include "unicode/numsys.h"
#include "unicode/unum.h"
#include "unicode/utf16.h"
#include "ucurrimp.h"
#include "cstring.h"
#include "locbased.h"
#include "uresimp.h"
#include "ureslocs.h"
#include "charstr.h"
#include "uassert.h"

// *****************************************************************************
// class DecimalFormatSymbols
// *****************************************************************************

U_NAMESPACE_BEGIN

UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DecimalFormatSymbols)

static const char gNumberElements[] = "NumberElements";
static const char gCurrencySpacingTag[] = "currencySpacing";
static const char gBeforeCurrencyTag[] = "beforeCurrency";
static const char gAfterCurrencyTag[] = "afterCurrency";
static const char gCurrencyMatchTag[] = "currencyMatch";
static const char gCurrencySudMatchTag[] = "surroundingMatch";
static const char gCurrencyInsertBtnTag[] = "insertBetween";
static const char gLatn[] =  "latn";
static const char gSymbols[] = "symbols";
static const char gNumberElementsLatnSymbols[] = "NumberElements/latn/symbols";

static const UChar INTL_CURRENCY_SYMBOL_STR[] = {0xa4, 0xa4, 0};

// List of field names to be loaded from the data files.
// These are parallel with the enum ENumberFormatSymbol in unicode/dcfmtsym.h.
static const char *gNumberElementKeys[DecimalFormatSymbols::kFormatSymbolCount] = {
    "decimal",
    "group",
    NULL, /* #11897: the <list> symbol is NOT the pattern separator symbol */
    "percentSign",
    NULL, /* Native zero digit is deprecated from CLDR - get it from the numbering system */
    NULL, /* Pattern digit character is deprecated from CLDR - use # by default always */
    "minusSign",
    "plusSign",
    NULL, /* currency symbol - Wait until we know the currency before loading from CLDR */
    NULL, /* intl currency symbol - Wait until we know the currency before loading from CLDR */
    "currencyDecimal",
    "exponential",
    "perMille",
    NULL, /* Escape padding character - not in CLDR */
    "infinity",
    "nan",
    NULL, /* Significant digit symbol - not in CLDR */
    "currencyGroup",
    NULL, /* one digit - get it from the numbering system */
    NULL, /* two digit - get it from the numbering system */
    NULL, /* three digit - get it from the numbering system */
    NULL, /* four digit - get it from the numbering system */
    NULL, /* five digit - get it from the numbering system */
    NULL, /* six digit - get it from the numbering system */
    NULL, /* seven digit - get it from the numbering system */
    NULL, /* eight digit - get it from the numbering system */
    NULL, /* nine digit - get it from the numbering system */
    "superscriptingExponent", /* Multiplication (x) symbol for exponents */
    "approximatelySign" /* Approximately sign symbol */
};

// -------------------------------------
// Initializes this with the decimal format symbols in the default locale.

DecimalFormatSymbols::DecimalFormatSymbols(UErrorCode& status)
        : UObject(), locale(), currPattern(NULL) {
    initialize(locale, status, TRUE);
}

// -------------------------------------
// Initializes this with the decimal format symbols in the desired locale.

DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, UErrorCode& status)
        : UObject(), locale(loc), currPattern(NULL) {
    initialize(locale, status);
}

DecimalFormatSymbols::DecimalFormatSymbols(const Locale& loc, const NumberingSystem& ns, UErrorCode& status)
        : UObject(), locale(loc), currPattern(NULL) {
    initialize(locale, status, FALSE, &ns);
}

DecimalFormatSymbols::DecimalFormatSymbols()
        : UObject(), locale(Locale::getRoot()), currPattern(NULL) {
    *validLocale = *actualLocale = 0;
    initialize();
}

DecimalFormatSymbols*
DecimalFormatSymbols::createWithLastResortData(UErrorCode& status) {
    if (U_FAILURE(status)) { return NULL; }
    DecimalFormatSymbols* sym = new DecimalFormatSymbols();
    if (sym == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
    }
    return sym;
}

// -------------------------------------

DecimalFormatSymbols::~DecimalFormatSymbols()
{
}

// -------------------------------------
// copy constructor

DecimalFormatSymbols::DecimalFormatSymbols(const DecimalFormatSymbols &source)
    : UObject(source)
{
    *this = source;
}

// -------------------------------------
// assignment operator

DecimalFormatSymbols&
DecimalFormatSymbols::operator=(const DecimalFormatSymbols& rhs)
{
    if (this != &rhs) {
        for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) {
            // fastCopyFrom is safe, see docs on fSymbols
            fSymbols[(ENumberFormatSymbol)i].fastCopyFrom(rhs.fSymbols[(ENumberFormatSymbol)i]);
        }
        for(int32_t i = 0; i < (int32_t)UNUM_CURRENCY_SPACING_COUNT; ++i) {
            currencySpcBeforeSym[i].fastCopyFrom(rhs.currencySpcBeforeSym[i]);
            currencySpcAfterSym[i].fastCopyFrom(rhs.currencySpcAfterSym[i]);
        }
        locale = rhs.locale;
        uprv_strcpy(validLocale, rhs.validLocale);
        uprv_strcpy(actualLocale, rhs.actualLocale);
        fIsCustomCurrencySymbol = rhs.fIsCustomCurrencySymbol; 
        fIsCustomIntlCurrencySymbol = rhs.fIsCustomIntlCurrencySymbol; 
        fCodePointZero = rhs.fCodePointZero;
        currPattern = rhs.currPattern;
    }
    return *this;
}

// -------------------------------------

bool
DecimalFormatSymbols::operator==(const DecimalFormatSymbols& that) const
{
    if (this == &that) {
        return true;
    }
    if (fIsCustomCurrencySymbol != that.fIsCustomCurrencySymbol) { 
        return false;
    } 
    if (fIsCustomIntlCurrencySymbol != that.fIsCustomIntlCurrencySymbol) { 
        return false;
    } 
    for(int32_t i = 0; i < (int32_t)kFormatSymbolCount; ++i) {
        if(fSymbols[(ENumberFormatSymbol)i] != that.fSymbols[(ENumberFormatSymbol)i]) {
            return false;
        }
    }
    for(int32_t i = 0; i < (int32_t)UNUM_CURRENCY_SPACING_COUNT; ++i) {
        if(currencySpcBeforeSym[i] != that.currencySpcBeforeSym[i]) {
            return false;
        }
        if(currencySpcAfterSym[i] != that.currencySpcAfterSym[i]) {
            return false;
        }
    }
    // No need to check fCodePointZero since it is based on fSymbols
    return locale == that.locale &&
        uprv_strcmp(validLocale, that.validLocale) == 0 &&
        uprv_strcmp(actualLocale, that.actualLocale) == 0;
}

// -------------------------------------

namespace {

/**
 * Sink for enumerating all of the decimal format symbols (more specifically, anything
 * under the "NumberElements.symbols" tree).
 *
 * More specific bundles (en_GB) are enumerated before their parents (en_001, en, root):
 * Only store a value if it is still missing, that is, it has not been overridden.
 */
struct DecFmtSymDataSink : public ResourceSink {

    // Destination for data, modified via setters.
    DecimalFormatSymbols& dfs;
    // Boolean array of whether or not we have seen a particular symbol yet.
    // Can't simply check fSymbols because it is pre-populated with defaults.
    UBool seenSymbol[DecimalFormatSymbols::kFormatSymbolCount];

    // Constructor/Destructor
    DecFmtSymDataSink(DecimalFormatSymbols& _dfs) : dfs(_dfs) {
        uprv_memset(seenSymbol, FALSE, sizeof(seenSymbol));
    }
    virtual ~DecFmtSymDataSink();

    virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
            UErrorCode &errorCode) override {
        ResourceTable symbolsTable = value.getTable(errorCode);
        if (U_FAILURE(errorCode)) { return; }
        for (int32_t j = 0; symbolsTable.getKeyAndValue(j, key, value); ++j) {
            for (int32_t i=0; i<DecimalFormatSymbols::kFormatSymbolCount; i++) {
                if (gNumberElementKeys[i] != NULL && uprv_strcmp(key, gNumberElementKeys[i]) == 0) {
                    if (!seenSymbol[i]) {
                        seenSymbol[i] = TRUE;
                        dfs.setSymbol(
                            (DecimalFormatSymbols::ENumberFormatSymbol) i,
                            value.getUnicodeString(errorCode));
                        if (U_FAILURE(errorCode)) { return; }
                    }
                    break;
                }
            }
        }
    }

    // Returns true if all the symbols have been seen.
    UBool seenAll() {
        for (int32_t i=0; i<DecimalFormatSymbols::kFormatSymbolCount; i++) {
            if (!seenSymbol[i]) {
                return FALSE;
            }
        }
        return TRUE;
    }

    // If monetary decimal or grouping were not explicitly set, then set them to be the
    // same as their non-monetary counterparts.
    void resolveMissingMonetarySeparators(const UnicodeString* fSymbols) {
        if (!seenSymbol[DecimalFormatSymbols::kMonetarySeparatorSymbol]) {
            dfs.setSymbol(
                DecimalFormatSymbols::kMonetarySeparatorSymbol,
                fSymbols[DecimalFormatSymbols::kDecimalSeparatorSymbol]);
        }
        if (!seenSymbol[DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol]) {
            dfs.setSymbol(
                DecimalFormatSymbols::kMonetaryGroupingSeparatorSymbol,
                fSymbols[DecimalFormatSymbols::kGroupingSeparatorSymbol]);
        }
    }
};

struct CurrencySpacingSink : public ResourceSink {
    DecimalFormatSymbols& dfs;
    UBool hasBeforeCurrency;
    UBool hasAfterCurrency;

    CurrencySpacingSink(DecimalFormatSymbols& _dfs)
        : dfs(_dfs), hasBeforeCurrency(FALSE), hasAfterCurrency(FALSE) {}
    virtual ~CurrencySpacingSink();

    virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
            UErrorCode &errorCode) override {
        ResourceTable spacingTypesTable = value.getTable(errorCode);
        for (int32_t i = 0; spacingTypesTable.getKeyAndValue(i, key, value); ++i) {
            UBool beforeCurrency;
            if (uprv_strcmp(key, gBeforeCurrencyTag) == 0) {
                beforeCurrency = TRUE;
                hasBeforeCurrency = TRUE;
            } else if (uprv_strcmp(key, gAfterCurrencyTag) == 0) {
                beforeCurrency = FALSE;
                hasAfterCurrency = TRUE;
            } else {
                continue;
            }

            ResourceTable patternsTable = value.getTable(errorCode);
            for (int32_t j = 0; patternsTable.getKeyAndValue(j, key, value); ++j) {
                UCurrencySpacing pattern;
                if (uprv_strcmp(key, gCurrencyMatchTag) == 0) {
                    pattern = UNUM_CURRENCY_MATCH;
                } else if (uprv_strcmp(key, gCurrencySudMatchTag) == 0) {
                    pattern = UNUM_CURRENCY_SURROUNDING_MATCH;
                } else if (uprv_strcmp(key, gCurrencyInsertBtnTag) == 0) {
                    pattern = UNUM_CURRENCY_INSERT;
                } else {
                    continue;
                }

                const UnicodeString& current = dfs.getPatternForCurrencySpacing(
                    pattern, beforeCurrency, errorCode);
                if (current.isEmpty()) {
                    dfs.setPatternForCurrencySpacing(
                        pattern, beforeCurrency, value.getUnicodeString(errorCode));
                }
            }
        }
    }

    void resolveMissing() {
        // For consistency with Java, this method overwrites everything with the defaults unless
        // both beforeCurrency and afterCurrency were found in CLDR.
        static const char* defaults[] = { "[:letter:]", "[:digit:]", " " };
        if (!hasBeforeCurrency || !hasAfterCurrency) {
            for (UBool beforeCurrency = 0; beforeCurrency <= TRUE; beforeCurrency++) {
                for (int32_t pattern = 0; pattern < UNUM_CURRENCY_SPACING_COUNT; pattern++) {
                    dfs.setPatternForCurrencySpacing((UCurrencySpacing)pattern,
                        beforeCurrency, UnicodeString(defaults[pattern], -1, US_INV));
                }
            }
        }
    }
};

// Virtual destructors must be defined out of line.
DecFmtSymDataSink::~DecFmtSymDataSink() {}
CurrencySpacingSink::~CurrencySpacingSink() {}

} // namespace

void
DecimalFormatSymbols::initialize(const Locale& loc, UErrorCode& status,
    UBool useLastResortData, const NumberingSystem* ns)
{
    if (U_FAILURE(status)) { return; }
    *validLocale = *actualLocale = 0;

    // First initialize all the symbols to the fallbacks for anything we can't find
    initialize();

    //
    // Next get the numbering system for this locale and set zero digit
    // and the digit string based on the numbering system for the locale
    //
    LocalPointer<NumberingSystem> nsLocal;
    if (ns == nullptr) {
        // Use the numbering system according to the locale.
        // Save it into a LocalPointer so it gets cleaned up.
        nsLocal.adoptInstead(NumberingSystem::createInstance(loc, status));
        ns = nsLocal.getAlias();
    }
    const char *nsName;
    if (U_SUCCESS(status) && ns->getRadix() == 10 && !ns->isAlgorithmic()) {
        nsName = ns->getName();
        UnicodeString digitString(ns->getDescription());
        int32_t digitIndex = 0;
        UChar32 digit = digitString.char32At(0);
        fSymbols[kZeroDigitSymbol].setTo(digit);
        for (int32_t i = kOneDigitSymbol; i <= kNineDigitSymbol; ++i) {
            digitIndex += U16_LENGTH(digit);
            digit = digitString.char32At(digitIndex);
            fSymbols[i].setTo(digit);
        }
    } else {
        nsName = gLatn;
    }

    // Open resource bundles
    const char* locStr = loc.getName();
    LocalUResourceBundlePointer resource(ures_open(NULL, locStr, &status));
    LocalUResourceBundlePointer numberElementsRes(
        ures_getByKeyWithFallback(resource.getAlias(), gNumberElements, NULL, &status));

    if (U_FAILURE(status)) {
        if ( useLastResortData ) {
            status = U_USING_DEFAULT_WARNING;
            initialize();
        }
        return;
    }

    // Set locale IDs
    // TODO: Is there a way to do this without depending on the resource bundle instance?
    U_LOCALE_BASED(locBased, *this);
    locBased.setLocaleIDs(
        ures_getLocaleByType(
            numberElementsRes.getAlias(),
            ULOC_VALID_LOCALE, &status),
        ures_getLocaleByType(
            numberElementsRes.getAlias(),
            ULOC_ACTUAL_LOCALE, &status));

    // Now load the rest of the data from the data sink.
    // Start with loading this nsName if it is not Latin.
    DecFmtSymDataSink sink(*this);
    if (uprv_strcmp(nsName, gLatn) != 0) {
        CharString path;
        path.append(gNumberElements, status)
            .append('/', status)
            .append(nsName, status)
            .append('/', status)
            .append(gSymbols, status);
        ures_getAllItemsWithFallback(resource.getAlias(), path.data(), sink, status);

        // If no symbols exist for the given nsName and resource bundle, silently ignore
        // and fall back to Latin.
        if (status == U_MISSING_RESOURCE_ERROR) {
            status = U_ZERO_ERROR;
        } else if (U_FAILURE(status)) {
            return;
        }
    }

    // Continue with Latin if necessary.
    if (!sink.seenAll()) {
        ures_getAllItemsWithFallback(resource.getAlias(), gNumberElementsLatnSymbols, sink, status);
        if (U_FAILURE(status)) { return; }
    }

    // Let the monetary number separators equal the default number separators if necessary.
    sink.resolveMissingMonetarySeparators(fSymbols);

    // Resolve codePointZero
    UChar32 tempCodePointZero = -1;
    for (int32_t i=0; i<=9; i++) {
        const UnicodeString& stringDigit = getConstDigitSymbol(i);
        if (stringDigit.countChar32() != 1) {
            tempCodePointZero = -1;
            break;
        }
        UChar32 cp = stringDigit.char32At(0);
        if (i == 0) {
            tempCodePointZero = cp;
        } else if (cp != tempCodePointZero + i) {
            tempCodePointZero = -1;
            break;
        }
    }
    fCodePointZero = tempCodePointZero;

    // Get the default currency from the currency API.
    UErrorCode internalStatus = U_ZERO_ERROR; // don't propagate failures out
    UChar curriso[4];
    UnicodeString tempStr;
    int32_t currisoLength = ucurr_forLocale(locStr, curriso, UPRV_LENGTHOF(curriso), &internalStatus);
    if (U_SUCCESS(internalStatus) && currisoLength == 3) {
        setCurrency(curriso, status);
    } else {
        setCurrency(nullptr, status);
    }

    // Currency Spacing.
    LocalUResourceBundlePointer currencyResource(ures_open(U_ICUDATA_CURR, locStr, &status));
    CurrencySpacingSink currencySink(*this);
    ures_getAllItemsWithFallback(currencyResource.getAlias(), gCurrencySpacingTag, currencySink, status);
    currencySink.resolveMissing();
    if (U_FAILURE(status)) { return; }
}

void
DecimalFormatSymbols::initialize() {
    /*
     * These strings used to be in static arrays, but the HP/UX aCC compiler
     * cannot initialize a static array with class constructors.
     *  markus 2000may25
     */
    fSymbols[kDecimalSeparatorSymbol] = (UChar)0x2e;    // '.' decimal separator
    fSymbols[kGroupingSeparatorSymbol].remove();        //     group (thousands) separator
    fSymbols[kPatternSeparatorSymbol] = (UChar)0x3b;    // ';' pattern separator
    fSymbols[kPercentSymbol] = (UChar)0x25;             // '%' percent sign
    fSymbols[kZeroDigitSymbol] = (UChar)0x30;           // '0' native 0 digit
    fSymbols[kOneDigitSymbol] = (UChar)0x31;            // '1' native 1 digit
    fSymbols[kTwoDigitSymbol] = (UChar)0x32;            // '2' native 2 digit
    fSymbols[kThreeDigitSymbol] = (UChar)0x33;          // '3' native 3 digit
    fSymbols[kFourDigitSymbol] = (UChar)0x34;           // '4' native 4 digit
    fSymbols[kFiveDigitSymbol] = (UChar)0x35;           // '5' native 5 digit
    fSymbols[kSixDigitSymbol] = (UChar)0x36;            // '6' native 6 digit
    fSymbols[kSevenDigitSymbol] = (UChar)0x37;          // '7' native 7 digit
    fSymbols[kEightDigitSymbol] = (UChar)0x38;          // '8' native 8 digit
    fSymbols[kNineDigitSymbol] = (UChar)0x39;           // '9' native 9 digit
    fSymbols[kDigitSymbol] = (UChar)0x23;               // '#' pattern digit
    fSymbols[kPlusSignSymbol] = (UChar)0x002b;          // '+' plus sign
    fSymbols[kMinusSignSymbol] = (UChar)0x2d;           // '-' minus sign
    fSymbols[kCurrencySymbol] = (UChar)0xa4;            // 'OX' currency symbol
    fSymbols[kIntlCurrencySymbol].setTo(TRUE, INTL_CURRENCY_SYMBOL_STR, 2);
    fSymbols[kMonetarySeparatorSymbol] = (UChar)0x2e;   // '.' monetary decimal separator
    fSymbols[kExponentialSymbol] = (UChar)0x45;         // 'E' exponential
    fSymbols[kPerMillSymbol] = (UChar)0x2030;           // '%o' per mill
    fSymbols[kPadEscapeSymbol] = (UChar)0x2a;           // '*' pad escape symbol
    fSymbols[kInfinitySymbol] = (UChar)0x221e;          // 'oo' infinite
    fSymbols[kNaNSymbol] = (UChar)0xfffd;               // SUB NaN
    fSymbols[kSignificantDigitSymbol] = (UChar)0x0040;  // '@' significant digit
    fSymbols[kMonetaryGroupingSeparatorSymbol].remove(); // 
    fSymbols[kExponentMultiplicationSymbol] = (UChar)0xd7; // 'x' multiplication symbol for exponents
    fSymbols[kApproximatelySignSymbol] = u'~';          // '~' approximately sign
    fIsCustomCurrencySymbol = FALSE; 
    fIsCustomIntlCurrencySymbol = FALSE;
    fCodePointZero = 0x30;
    U_ASSERT(fCodePointZero == fSymbols[kZeroDigitSymbol].char32At(0));
    currPattern = nullptr;

}

void DecimalFormatSymbols::setCurrency(const UChar* currency, UErrorCode& status) {
    // TODO: If this method is made public:
    // - Adopt ICU4J behavior of not allowing currency to be null.
    // - Also verify that the length of currency is 3.
    if (!currency) {
        return;
    }

    UnicodeString tempStr;
    uprv_getStaticCurrencyName(currency, locale.getName(), tempStr, status);
    if (U_SUCCESS(status)) {
        fSymbols[kIntlCurrencySymbol].setTo(currency, 3);
        fSymbols[kCurrencySymbol] = tempStr;
    }

    char cc[4]={0};
    u_UCharsToChars(currency, cc, 3);

    /* An explicit currency was requested */
    // TODO(ICU-13297): Move this data loading logic into a centralized place
    UErrorCode localStatus = U_ZERO_ERROR;
    LocalUResourceBundlePointer rbTop(ures_open(U_ICUDATA_CURR, locale.getName(), &localStatus));
    LocalUResourceBundlePointer rb(
        ures_getByKeyWithFallback(rbTop.getAlias(), "Currencies", NULL, &localStatus));
    ures_getByKeyWithFallback(rb.getAlias(), cc, rb.getAlias(), &localStatus);
    if(U_SUCCESS(localStatus) && ures_getSize(rb.getAlias())>2) { // the length is 3 if more data is present
        ures_getByIndex(rb.getAlias(), 2, rb.getAlias(), &localStatus);
        int32_t currPatternLen = 0;
        currPattern =
            ures_getStringByIndex(rb.getAlias(), (int32_t)0, &currPatternLen, &localStatus);
        UnicodeString decimalSep =
            ures_getUnicodeStringByIndex(rb.getAlias(), (int32_t)1, &localStatus);
        UnicodeString groupingSep =
            ures_getUnicodeStringByIndex(rb.getAlias(), (int32_t)2, &localStatus);
        if(U_SUCCESS(localStatus)){
            fSymbols[kMonetaryGroupingSeparatorSymbol] = groupingSep;
            fSymbols[kMonetarySeparatorSymbol] = decimalSep;
            //pattern.setTo(TRUE, currPattern, currPatternLen);
        }
    }
    /* else An explicit currency was requested and is unknown or locale data is malformed. */
    /* ucurr_* API will get the correct value later on. */
}

Locale
DecimalFormatSymbols::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
    U_LOCALE_BASED(locBased, *this);
    return locBased.getLocale(type, status);
}

const UnicodeString&
DecimalFormatSymbols::getPatternForCurrencySpacing(UCurrencySpacing type,
                                                 UBool beforeCurrency,
                                                 UErrorCode& status) const {
    if (U_FAILURE(status)) {
      return fNoSymbol;  // always empty.
    }
    if (beforeCurrency) {
      return currencySpcBeforeSym[(int32_t)type];
    } else {
      return currencySpcAfterSym[(int32_t)type];
    }
}

void
DecimalFormatSymbols::setPatternForCurrencySpacing(UCurrencySpacing type,
                                                   UBool beforeCurrency,
                                             const UnicodeString& pattern) {
  if (beforeCurrency) {
    currencySpcBeforeSym[(int32_t)type] = pattern;
  } else {
    currencySpcAfterSym[(int32_t)type] =  pattern;
  }
}
U_NAMESPACE_END

#endif /* #if !UCONFIG_NO_FORMATTING */

//eof
