Commit message: ICU-20246 Fixing another integer overflow in number parsing.
CVE: CVE-2018-18928
CWE: CWE-190
Vulnerability description: International Components for Unicode (ICU) for C/C++ 63.1 has an integer overflow in number::impl::DecimalQuantity::toScientificString() in i18n/number_decimalquantity.cpp.

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestRounding() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);

    if (U_FAILURE(status)) {
        dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
        return;
    }

    int roundingIncrements[]={1, 2, 5, 20, 50, 100};
    int testValues[]={0, 300};

    for (int j=0; j<2; j++) {
        for (int mode=DecimalFormat::kRoundUp;mode<DecimalFormat::kRoundHalfEven;mode++) {
            df->setRoundingMode((DecimalFormat::ERoundingMode)mode);
            for (int increment=0; increment<6; increment++) {
                double base=testValues[j];
                double rInc=roundingIncrements[increment];
                checkRounding(df, base, 20, rInc);
                rInc=1.000000000/rInc;
                checkRounding(df, base, 20, rInc);
            }
        }
    }
    delete df;
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::copyBcdFrom(const DecimalQuantity &other) {
    setBcdToZero();
    if (other.usingBytes) {
        ensureCapacity(other.precision);
        uprv_memcpy(fBCD.bcdBytes.ptr, other.fBCD.bcdBytes.ptr, other.precision * sizeof(int8_t));
    } else {
        fBCD.bcdLong = other.fBCD.bcdLong;
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expectPad(DecimalFormat& fmt, const UnicodeString& pat,
                                 int32_t pos, int32_t width, UChar pad) {
    expectPad(fmt, pat, pos, width, UnicodeString(pad));
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestWhiteSpaceParsing(void) {
    UErrorCode ec = U_ZERO_ERROR;
    DecimalFormatSymbols US(Locale::getUS(), ec);
    DecimalFormat fmt("a  b#0c  ", US, ec);
    if (U_FAILURE(ec)) {
        errcheckln(ec, "FAIL: Constructor - %s", u_errorName(ec));
        return;
    }
    // From ICU 62, flexible whitespace needs lenient mode
    fmt.setLenient(TRUE);
    int32_t n = 1234;
    expect(fmt, "a b1234c ", n);
    expect(fmt, "a   b1234c   ", n);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestLocalizedPatternSymbolCoverage() {
    IcuTestErrorCode errorCode(*this, "TestLocalizedPatternSymbolCoverage");
    // Ticket #12961: DecimalFormat::toLocalizedPattern() is not working as designed.
    DecimalFormatSymbols dfs(errorCode);
    dfs.setSymbol(DecimalFormatSymbols::kGroupingSeparatorSymbol, u'⁖');
    dfs.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, u'⁘');
    dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u'⁙');
    dfs.setSymbol(DecimalFormatSymbols::kDigitSymbol, u'▰');
    dfs.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, u'໐');
    dfs.setSymbol(DecimalFormatSymbols::kSignificantDigitSymbol, u'⁕');
    dfs.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, u'†');
    dfs.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, u'‡');
    dfs.setSymbol(DecimalFormatSymbols::kPercentSymbol, u'⁜');
    dfs.setSymbol(DecimalFormatSymbols::kPerMillSymbol, u'‱');
    dfs.setSymbol(DecimalFormatSymbols::kExponentialSymbol, u"⁑⁑"); // tests multi-char sequence
    dfs.setSymbol(DecimalFormatSymbols::kPadEscapeSymbol, u'⁂');

    {
        UnicodeString standardPattern(u"#,##0.05+%;#,##0.05-%");
        UnicodeString localizedPattern(u"▰⁖▰▰໐⁘໐໕†⁜⁙▰⁖▰▰໐⁘໐໕‡⁜");

        DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
        df1.applyPattern(standardPattern, errorCode);
        DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
        df2.applyLocalizedPattern(localizedPattern, errorCode);
        assertTrue("DecimalFormat instances should be equal", df1 == df2);
        UnicodeString p2;
        assertEquals("toPattern should match on localizedPattern instance",
                standardPattern, df2.toPattern(p2));
        UnicodeString lp1;
        assertEquals("toLocalizedPattern should match on standardPattern instance",
                localizedPattern, df1.toLocalizedPattern(lp1));
    }

    {
        UnicodeString standardPattern(u"* @@@E0‰");
        UnicodeString localizedPattern(u"⁂ ⁕⁕⁕⁑⁑໐‱");

        DecimalFormat df1("#", new DecimalFormatSymbols(dfs), errorCode);
        df1.applyPattern(standardPattern, errorCode);
        DecimalFormat df2("#", new DecimalFormatSymbols(dfs), errorCode);
        df2.applyLocalizedPattern(localizedPattern, errorCode);
        assertTrue("DecimalFormat instances should be equal", df1 == df2);
        UnicodeString p2;
        assertEquals("toPattern should match on localizedPattern instance",
                standardPattern, df2.toPattern(p2));
        UnicodeString lp1;
        assertEquals("toLocalizedPattern should match on standardPattern instance",
                localizedPattern, df1.toLocalizedPattern(lp1));
    }
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::_setToLong(int64_t n) {
    if (n == INT64_MIN) {
        DecNum decnum;
        UErrorCode localStatus = U_ZERO_ERROR;
        decnum.setTo("9.223372036854775808E+18", localStatus);
        if (U_FAILURE(localStatus)) { return; } // unexpected
        flags |= NEGATIVE_FLAG;
        readDecNumberToBcd(decnum);
    } else if (n <= INT32_MAX) {
        readIntToBcd(static_cast<int32_t>(n));
    } else {
        readLongToBcd(n);
    }
}

Project: icu
File: fmtable.cpp

Formattable::Formattable(int32_t value)
{
    init();
    fValue.fInt64 = value;
}

Project: icu
File: number_decimalquantity.cpp

bool DecimalQuantity::isZero() const {
    return precision == 0;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCtorApplyPatternDifference() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols sym("en_US", status);
    UnicodeString pattern("\\u00a40");
    DecimalFormat fmt(pattern.unescape(), sym, status);
    if (U_FAILURE(status)) {
        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
        return;
    }
    UnicodeString result;
    assertEquals(
            "ctor favors precision of currency",
            "$5.00",
            fmt.format((double)5, result));
    result.remove();
    fmt.applyPattern(pattern.unescape(), status);
    assertEquals(
            "applyPattern favors precision of pattern",
            "$5",
            fmt.format((double)5, result));
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestRoundingPattern() {
    UErrorCode status = U_ZERO_ERROR;
    struct {
        UnicodeString  pattern;
        double        testCase;
        UnicodeString expected;
    } tests[] = {
            { (UnicodeString)"##0.65", 1.234, (UnicodeString)"1.30" },
            { (UnicodeString)"#50",    1230,  (UnicodeString)"1250" }
    };
    int32_t numOfTests = UPRV_LENGTHOF(tests);
    UnicodeString result;

    DecimalFormat *df = (DecimalFormat*)NumberFormat::createCurrencyInstance(Locale::getEnglish(), status);
    if (U_FAILURE(status)) {
        dataerrln("Unable to create decimal formatter. - %s", u_errorName(status));
        return;
    }

    for (int32_t i = 0; i < numOfTests; i++) {
        result.remove();

        df->applyPattern(tests[i].pattern, status);
        if (U_FAILURE(status)) {
            errln("Unable to apply pattern to decimal formatter. - %s", u_errorName(status));
        }

        df->format(tests[i].testCase, result);

        if (result != tests[i].expected) {
            errln("String Pattern Rounding Test Failed: Pattern: \"" + tests[i].pattern + "\" Number: " + tests[i].testCase + " - Got: " + result + " Expected: " + tests[i].expected);
        }
    }

    delete df;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestComplexCurrency() {

//    UErrorCode ec = U_ZERO_ERROR;
//    Locale loc("kn", "IN", "");
//    NumberFormat* fmt = NumberFormat::createCurrencyInstance(loc, ec);
//    if (U_SUCCESS(ec)) {
//        expect2(*fmt, 1.0, CharsToUnicodeString("Re.\\u00A01.00"));
//        Use .00392625 because that's 2^-8.  Any value less than 0.005 is fine.
//        expect(*fmt, 1.00390625, CharsToUnicodeString("Re.\\u00A01.00")); // tricky
//        expect2(*fmt, 12345678.0, CharsToUnicodeString("Rs.\\u00A01,23,45,678.00"));
//        expect2(*fmt, 0.5, CharsToUnicodeString("Rs.\\u00A00.50"));
//        expect2(*fmt, -1.0, CharsToUnicodeString("-Re.\\u00A01.00"));
//        expect2(*fmt, -10.0, CharsToUnicodeString("-Rs.\\u00A010.00"));
//    } else {
//        errln("FAIL: getCurrencyInstance(kn_IN)");
//    }
//    delete fmt;

}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCurrencyFormat()
{
    // This test is here to increase code coverage.
    UErrorCode status = U_ZERO_ERROR;
    MeasureFormat *cloneObj;
    UnicodeString str;
    Formattable toFormat, result;
    static const UChar ISO_CODE[4] = {0x0047, 0x0042, 0x0050, 0};

    Locale  saveDefaultLocale = Locale::getDefault();
    Locale::setDefault( Locale::getUK(), status );
    if (U_FAILURE(status)) {
        errln("couldn't set default Locale!");
        return;
    }

    MeasureFormat *measureObj = MeasureFormat::createCurrencyFormat(status);
    Locale::setDefault( saveDefaultLocale, status );
    if (U_FAILURE(status)){
        dataerrln("FAIL: Status %s", u_errorName(status));
        return;
    }
    cloneObj = (MeasureFormat *)measureObj->clone();
    if (cloneObj == NULL) {
        errln("Clone doesn't work");
        return;
    }
    toFormat.adoptObject(new CurrencyAmount(1234.56, ISO_CODE, status));
    measureObj->format(toFormat, str, status);
    measureObj->parseObject(str, result, status);
    if (U_FAILURE(status)){
        errln("FAIL: Status %s", u_errorName(status));
    }
    if (result != toFormat) {
        errln("measureObj does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
    }
    status = U_ZERO_ERROR;
    str.truncate(0);
    cloneObj->format(toFormat, str, status);
    cloneObj->parseObject(str, result, status);
    if (U_FAILURE(status)){
        errln("FAIL: Status %s", u_errorName(status));
    }
    if (result != toFormat) {
        errln("Clone does not round trip. Formatted string was \"" + str + "\" Got: " + toString(result) + " Expected: " + toString(toFormat));
    }
    if (*measureObj != *cloneObj) {
        errln("Cloned object is not equal to the original object");
    }
    delete measureObj;
    delete cloneObj;

    status = U_USELESS_COLLATOR_ERROR;
    if (MeasureFormat::createCurrencyFormat(status) != NULL) {
        errln("createCurrencyFormat should have returned NULL.");
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestEquality() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols symbols(Locale("root"), status);
    if (U_FAILURE(status)) {
    	dataerrln("Fail: can't create DecimalFormatSymbols for root");
    	return;
    }
    UnicodeString pattern("#,##0.###");
    DecimalFormat fmtBase(pattern, symbols, status);
    if (U_FAILURE(status)) {
    	dataerrln("Fail: can't create DecimalFormat using root symbols");
    	return;
    }

    DecimalFormat* fmtClone = (DecimalFormat*)fmtBase.clone();
    fmtClone->setFormatWidth(fmtBase.getFormatWidth() + 32);
    if (*fmtClone == fmtBase) {
        errln("Error: DecimalFormat == does not distinguish objects that differ only in FormatWidth");
    }
    delete fmtClone;
}

Project: icu
File: fmtable.cpp

Formattable::operator=(const Formattable& source)
{
    if (this != &source)
    {
        // Disposes the current formattable value/setting.
        dispose();

        // Sets the correct data type for this value.
        fType = source.fType;
        switch (fType)
        {
        case kArray:
            // Sets each element in the array one by one and records the array count.
            fValue.fArrayAndCount.fCount = source.fValue.fArrayAndCount.fCount;
            fValue.fArrayAndCount.fArray = createArrayCopy(source.fValue.fArrayAndCount.fArray,
                                                           source.fValue.fArrayAndCount.fCount);
            break;
        case kString:
            // Sets the string value.
            fValue.fString = new UnicodeString(*source.fValue.fString);
            break;
        case kDouble:
            // Sets the double value.
            fValue.fDouble = source.fValue.fDouble;
            break;
        case kLong:
        case kInt64:
            // Sets the long value.
            fValue.fInt64 = source.fValue.fInt64;
            break;
        case kDate:
            // Sets the Date value.
            fValue.fDate = source.fValue.fDate;
            break;
        case kObject:
            fValue.fObject = objectClone(source.fValue.fObject);
            break;
        }

        UErrorCode status = U_ZERO_ERROR;
        if (source.fDecimalQuantity != NULL) {
          fDecimalQuantity = new DecimalQuantity(*source.fDecimalQuantity);
        }
        if (source.fDecimalStr != NULL) {
            fDecimalStr = new CharString(*source.fDecimalStr, status);
            if (U_FAILURE(status)) {
                delete fDecimalStr;
                fDecimalStr = NULL;
            }
        }
    }
    return *this;
}

Project: icu
File: numfmtst.cpp

    StubNumberFormat(){};

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestRegCurrency(void) {
#if !UCONFIG_NO_SERVICE
    UErrorCode status = U_ZERO_ERROR;
    UChar USD[4];
    ucurr_forLocale("en_US", USD, 4, &status);
    UChar YEN[4];
    ucurr_forLocale("ja_JP", YEN, 4, &status);
    UChar TMP[4];
    static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
    if(U_FAILURE(status)) {
        errcheckln(status, "Unable to get currency for locale, error %s", u_errorName(status));
        return;
    }

    UCurrRegistryKey enkey = ucurr_register(YEN, "en_US", &status);
    UCurrRegistryKey enUSEUROkey = ucurr_register(QQQ, "en_US_EURO", &status);

    ucurr_forLocale("en_US", TMP, 4, &status);
    if (u_strcmp(YEN, TMP) != 0) {
        errln("FAIL: didn't return YEN registered for en_US");
    }

    ucurr_forLocale("en_US_EURO", TMP, 4, &status);
    if (u_strcmp(QQQ, TMP) != 0) {
        errln("FAIL: didn't return QQQ for en_US_EURO");
    }

    int32_t fallbackLen = ucurr_forLocale("en_XX_BAR", TMP, 4, &status);
    if (fallbackLen) {
        errln("FAIL: tried to fallback en_XX_BAR");
    }
    status = U_ZERO_ERROR; // reset

    if (!ucurr_unregister(enkey, &status)) {
        errln("FAIL: couldn't unregister enkey");
    }

    ucurr_forLocale("en_US", TMP, 4, &status);
    if (u_strcmp(USD, TMP) != 0) {
        errln("FAIL: didn't return USD for en_US after unregister of en_US");
    }
    status = U_ZERO_ERROR; // reset

    ucurr_forLocale("en_US_EURO", TMP, 4, &status);
    if (u_strcmp(QQQ, TMP) != 0) {
        errln("FAIL: didn't return QQQ for en_US_EURO after unregister of en_US");
    }

    ucurr_forLocale("en_US_BLAH", TMP, 4, &status);
    if (u_strcmp(USD, TMP) != 0) {
        errln("FAIL: could not find USD for en_US_BLAH after unregister of en");
    }
    status = U_ZERO_ERROR; // reset

    if (!ucurr_unregister(enUSEUROkey, &status)) {
        errln("FAIL: couldn't unregister enUSEUROkey");
    }

    ucurr_forLocale("en_US_EURO", TMP, 4, &status);
    if (u_strcmp(EUR, TMP) != 0) {
        errln("FAIL: didn't return EUR for en_US_EURO after unregister of en_US_EURO");
    }
    status = U_ZERO_ERROR; // reset
#endif
}

Project: icu
File: numfmtst.cpp

static UChar toHexString(int32_t i) { return (UChar)(i + (i < 10 ? 0x30 : (0x41 - 10))); }

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestNonpositiveMultiplier() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols US(Locale::getUS(), status);
    CHECK(status, "DecimalFormatSymbols constructor");
    DecimalFormat df(UnicodeString("0"), US, status);
    CHECK(status, "DecimalFormat(0)");

    // test zero multiplier

    int32_t mult = df.getMultiplier();
    df.setMultiplier(0);
    if (df.getMultiplier() != mult) {
        errln("DecimalFormat.setMultiplier(0) did not ignore its zero input");
    }

    // test negative multiplier

    df.setMultiplier(-1);
    if (df.getMultiplier() != -1) {
        errln("DecimalFormat.setMultiplier(-1) ignored its negative input");
        return;
    }

    expect(df, "1122.123", -1122.123);
    expect(df, "-1122.123", 1122.123);
    expect(df, "1.2", -1.2);
    expect(df, "-1.2", 1.2);

    // Note:  the tests with the final parameter of FALSE will not round trip.
    //        The initial numeric value will format correctly, after the multiplier.
    //        Parsing the formatted text will be out-of-range for an int64, however.
    //        The expect() function could be modified to detect this and fall back
    //        to looking at the decimal parsed value, but it doesn't.
    expect(df, U_INT64_MIN,    "9223372036854775808", FALSE);
    expect(df, U_INT64_MIN+1,  "9223372036854775807");
    expect(df, (int64_t)-123,                  "123");
    expect(df, (int64_t)123,                  "-123");
    expect(df, U_INT64_MAX-1, "-9223372036854775806");
    expect(df, U_INT64_MAX,   "-9223372036854775807");

    df.setMultiplier(-2);
    expect(df, -(U_INT64_MIN/2)-1, "-9223372036854775806");
    expect(df, -(U_INT64_MIN/2),   "-9223372036854775808");
    expect(df, -(U_INT64_MIN/2)+1, "-9223372036854775810", FALSE);

    df.setMultiplier(-7);
    expect(df, -(U_INT64_MAX/7)-1, "9223372036854775814", FALSE);
    expect(df, -(U_INT64_MAX/7),   "9223372036854775807");
    expect(df, -(U_INT64_MAX/7)+1, "9223372036854775800");

    // TODO: uncomment (and fix up) all the following int64_t tests once BigInteger is ported
    // (right now the big numbers get turned into doubles and lose tons of accuracy)
    //expect2(df, U_INT64_MAX, Int64ToUnicodeString(-U_INT64_MAX));
    //expect2(df, U_INT64_MIN, UnicodeString(Int64ToUnicodeString(U_INT64_MIN), 1));
    //expect2(df, U_INT64_MAX / 2, Int64ToUnicodeString(-(U_INT64_MAX / 2)));
    //expect2(df, U_INT64_MIN / 2, Int64ToUnicodeString(-(U_INT64_MIN / 2)));

    // TODO: uncomment (and fix up) once BigDecimal is ported and DecimalFormat can handle it
    //expect2(df, BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
    //expect2(df, BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
    //expect2(df, java.math.BigDecimal.valueOf(Long.MAX_VALUE), java.math.BigDecimal.valueOf(Long.MAX_VALUE).negate().toString());
    //expect2(df, java.math.BigDecimal.valueOf(Long.MIN_VALUE), java.math.BigDecimal.valueOf(Long.MIN_VALUE).negate().toString());
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestMultiCurrencySign() {
    const char* DATA[][6] = {
        // the fields in the following test are:
        // locale,
        // currency pattern (with negative pattern),
        // currency number to be formatted,
        // currency format using currency symbol name, such as "$" for USD,
        // currency format using currency ISO name, such as "USD",
        // currency format using plural name, such as "US dollars".
        // for US locale
        {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1234.56", "$1,234.56", "USD\\u00A01,234.56", "US dollars\\u00A01,234.56"},
        {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "-1234.56", "-$1,234.56", "-USD\\u00A01,234.56", "-US dollars\\u00A01,234.56"},
        {"en_US", "\\u00A4#,##0.00;-\\u00A4#,##0.00", "1", "$1.00", "USD\\u00A01.00", "US dollars\\u00A01.00"},
        // for CHINA locale
        {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1234.56", "\\uFFE51,234.56", "CNY\\u00A01,234.56", "\\u4EBA\\u6C11\\u5E01\\u00A01,234.56"},
        {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "-1234.56", "(\\uFFE51,234.56)", "(CNY\\u00A01,234.56)", "(\\u4EBA\\u6C11\\u5E01\\u00A01,234.56)"},
        {"zh_CN", "\\u00A4#,##0.00;(\\u00A4#,##0.00)", "1", "\\uFFE51.00", "CNY\\u00A01.00", "\\u4EBA\\u6C11\\u5E01\\u00A01.00"}
    };

    const UChar doubleCurrencySign[] = {0xA4, 0xA4, 0};
    UnicodeString doubleCurrencyStr(doubleCurrencySign);
    const UChar tripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
    UnicodeString tripleCurrencyStr(tripleCurrencySign);

    for (uint32_t i=0; i<UPRV_LENGTHOF(DATA); ++i) {
        const char* locale = DATA[i][0];
        UnicodeString pat = ctou(DATA[i][1]);
        double numberToBeFormat = atof(DATA[i][2]);
        UErrorCode status = U_ZERO_ERROR;
        DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale(locale), status);
        if (U_FAILURE(status)) {
            delete sym;
            continue;
        }
        for (int j=1; j<=3; ++j) {
            // j represents the number of currency sign in the pattern.
            if (j == 2) {
                pat = pat.findAndReplace(ctou("\\u00A4"), doubleCurrencyStr);
            } else if (j == 3) {
                pat = pat.findAndReplace(ctou("\\u00A4\\u00A4"), tripleCurrencyStr);
            }

            DecimalFormat* fmt = new DecimalFormat(pat, new DecimalFormatSymbols(*sym), status);
            if (U_FAILURE(status)) {
                errln("FAILED init DecimalFormat ");
                delete fmt;
                continue;
            }
            UnicodeString s;
            ((NumberFormat*) fmt)->format(numberToBeFormat, s);
            // DATA[i][3] is the currency format result using a
            // single currency sign.
            // DATA[i][4] is the currency format result using
            // double currency sign.
            // DATA[i][5] is the currency format result using
            // triple currency sign.
            // DATA[i][j+2] is the currency format result using
            // 'j' number of currency sign.
            UnicodeString currencyFormatResult = ctou(DATA[i][2+j]);
            if (s.compare(currencyFormatResult)) {
                errln("FAIL format: Expected " + currencyFormatResult + "; Got " + s);
            }
            // mix style parsing
            for (int k=3; k<=5; ++k) {
              // DATA[i][3] is the currency format result using a
              // single currency sign.
              // DATA[i][4] is the currency format result using
              // double currency sign.
              // DATA[i][5] is the currency format result using
              // triple currency sign.
              UnicodeString oneCurrencyFormat = ctou(DATA[i][k]);
              UErrorCode status = U_ZERO_ERROR;
              Formattable parseRes;
              fmt->parse(oneCurrencyFormat, parseRes, status);
              if (U_FAILURE(status) ||
                  (parseRes.getType() == Formattable::kDouble &&
                   parseRes.getDouble() != numberToBeFormat) ||
                  (parseRes.getType() == Formattable::kLong &&
                   parseRes.getLong() != numberToBeFormat)) {
                  errln("FAILED parse " + oneCurrencyFormat + "; (i, j, k): " +
                        i + ", " + j + ", " + k);
              }
            }
            delete fmt;
        }
        delete sym;
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestFormatFastpaths() {
    // get some additional case
    {
        UErrorCode status=U_ZERO_ERROR;
        DecimalFormat df(UnicodeString(u"0000"),status);
        if (U_FAILURE(status)) {
            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
        } else {
            int64_t long_number = 1;
            UnicodeString expect = "0001";
            UnicodeString result;
            FieldPosition pos;
            df.format(long_number, result, pos);
            if(U_FAILURE(status)||expect!=result) {
                dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s",
                          __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
             } else {
                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),""));
            }
        }
    }
    {
        UErrorCode status=U_ZERO_ERROR;
        DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
        if (U_FAILURE(status)) {
            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
        } else {
            int64_t long_number = U_INT64_MIN; // -9223372036854775808L;
            // uint8_t bits[8];
            // memcpy(bits,&long_number,8);
            // for(int i=0;i<8;i++) {
            //   logln("bits: %02X", (unsigned int)bits[i]);
            // }
            UnicodeString expect = "-9223372036854775808";
            UnicodeString result;
            FieldPosition pos;
            df.format(long_number, result, pos);
            if(U_FAILURE(status)||expect!=result) {
                dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775808",
                          __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
            } else {
                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775808");
            }
        }
    }
    {
        UErrorCode status=U_ZERO_ERROR;
        DecimalFormat df(UnicodeString(u"0000000000000000000"),status);
        if (U_FAILURE(status)) {
            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
        } else {
            int64_t long_number = U_INT64_MAX; // -9223372036854775808L;
            // uint8_t bits[8];
            // memcpy(bits,&long_number,8);
            // for(int i=0;i<8;i++) {
            //   logln("bits: %02X", (unsigned int)bits[i]);
            // }
            UnicodeString expect = "9223372036854775807";
            UnicodeString result;
            FieldPosition pos;
            df.format(long_number, result, pos);
            if(U_FAILURE(status)||expect!=result) {
                dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on U_INT64_MAX",
                          __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
            } else {
                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on U_INT64_MAX");
            }
        }
    }
    {
        UErrorCode status=U_ZERO_ERROR;
        DecimalFormat df(UnicodeString("0000000000000000000",""),status);
        if (U_FAILURE(status)) {
            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
        } else {
            int64_t long_number = 0;
            // uint8_t bits[8];
            // memcpy(bits,&long_number,8);
            // for(int i=0;i<8;i++) {
            //   logln("bits: %02X", (unsigned int)bits[i]);
            // }
            UnicodeString expect = "0000000000000000000";
            UnicodeString result;
            FieldPosition pos;
            df.format(long_number, result, pos);
            if(U_FAILURE(status)||expect!=result) {
                dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on 0",
                          __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
            } else {
                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on 0");
            }
        }
    }
    {
        UErrorCode status=U_ZERO_ERROR;
        DecimalFormat df(UnicodeString("0000000000000000000",""),status);
        if (U_FAILURE(status)) {
            dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
        } else {
            int64_t long_number = U_INT64_MIN + 1;
            UnicodeString expect = "-9223372036854775807";
            UnicodeString result;
            FieldPosition pos;
            df.format(long_number, result, pos);
            if(U_FAILURE(status)||expect!=result) {
                dataerrln("%s:%d FAIL: expected '%s' got '%s' status %s on -9223372036854775807",
                          __FILE__, __LINE__, CStr(expect)(), CStr(result)(), u_errorName(status));
            } else {
                logln("OK:  got expected '"+result+"' status "+UnicodeString(u_errorName(status),"")+" on -9223372036854775807");
            }
        }
    }
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::roundToIncrement(double roundingIncrement, RoundingMode roundingMode,
                                       int32_t maxFrac, UErrorCode& status) {
    // TODO(13701): Move the nickel check into a higher-level API.
    if (roundingIncrement == 0.05) {
        roundToMagnitude(-2, roundingMode, true, status);
        roundToMagnitude(-maxFrac, roundingMode, false, status);
        return;
    } else if (roundingIncrement == 0.5) {
        roundToMagnitude(-1, roundingMode, true, status);
        roundToMagnitude(-maxFrac, roundingMode, false, status);
        return;
    }
    // TODO(13701): This is innefficient.  Improve?
    // TODO(13701): Should we convert to decNumber instead?
    roundToInfinity();
    double temp = toDouble();
    temp /= roundingIncrement;
    // Use another DecimalQuantity to perform the actual rounding...
    DecimalQuantity dq;
    dq.setToDouble(temp);
    dq.roundToMagnitude(0, roundingMode, status);
    temp = dq.toDouble();
    temp *= roundingIncrement;
    setToDouble(temp);
    // Since we reset the value to a double, we need to specify the rounding boundary
    // in order to get the DecimalQuantity out of approximation mode.
    // NOTE: In Java, we have minMaxFrac, but in C++, the two are differentiated.
    roundToMagnitude(-maxFrac, roundingMode, status);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestSecondaryGrouping(void) {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols US(Locale::getUS(), status);
    CHECK(status, "DecimalFormatSymbols ct");

    DecimalFormat f("#,##,###", US, status);
    CHECK(status, "DecimalFormat ct");

    expect2(f, (int32_t)123456789L, "12,34,56,789");
    expectPat(f, "#,##,##0");
    f.applyPattern("#,###", status);
    CHECK(status, "applyPattern");

    f.setSecondaryGroupingSize(4);
    expect2(f, (int32_t)123456789L, "12,3456,789");
    expectPat(f, "#,####,##0");
    NumberFormat *g = NumberFormat::createInstance(Locale("hi", "IN"), status);
    CHECK_DATA(status, "createInstance(hi_IN)");

    UnicodeString out;
    int32_t l = (int32_t)1876543210L;
    g->format(l, out);
    delete g;
    // expect "1,87,65,43,210", but with Hindi digits
    //         01234567890123
    UBool ok = TRUE;
    if (out.length() != 14) {
        ok = FALSE;
    } else {
        for (int32_t i=0; i<out.length(); ++i) {
            UBool expectGroup = FALSE;
            switch (i) {
            case 1:
            case 4:
            case 7:
            case 10:
                expectGroup = TRUE;
                break;
            }
            // Later -- fix this to get the actual grouping
            // character from the resource bundle.
            UBool isGroup = (out.charAt(i) == 0x002C);
            if (isGroup != expectGroup) {
                ok = FALSE;
                break;
            }
        }
    }
    if (!ok) {
        errln((UnicodeString)"FAIL  Expected " + l +
              " x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got \"" +
              escape(out) + "\"");
    } else {
        logln((UnicodeString)"Ok    " + l +
              " x hi_IN -> \"" +
              escape(out) + "\"");
    }
}

Project: icu
File: fmtable.cpp

ufmt_getInt64(UFormattable *fmt, UErrorCode *status) {
  Formattable *obj = Formattable::fromUFormattable(fmt);
  return obj->getInt64(*status);
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestQuotes(void)
{
    UErrorCode status = U_ZERO_ERROR;
    UnicodeString *pat;
    DecimalFormatSymbols *sym = new DecimalFormatSymbols(Locale::getUS(), status);
    if (U_FAILURE(status)) {
        errcheckln(status, "Fail to create DecimalFormatSymbols - %s", u_errorName(status));
        delete sym;
        return;
    }
    pat = new UnicodeString("a'fo''o'b#");
    DecimalFormat *fmt = new DecimalFormat(*pat, *sym, status);
    UnicodeString s;
    ((NumberFormat*)fmt)->format((int32_t)123, s);
    logln((UnicodeString)"Pattern \"" + *pat + "\"");
    logln((UnicodeString)" Format 123 -> " + escape(s));
    if (!(s=="afo'ob123"))
        errln((UnicodeString)"FAIL: Expected afo'ob123");

    s.truncate(0);
    delete fmt;
    delete pat;

    pat = new UnicodeString("a''b#");
    fmt = new DecimalFormat(*pat, *sym, status);
    ((NumberFormat*)fmt)->format((int32_t)123, s);
    logln((UnicodeString)"Pattern \"" + *pat + "\"");
    logln((UnicodeString)" Format 123 -> " + escape(s));
    if (!(s=="a'b123"))
        errln((UnicodeString)"FAIL: Expected a'b123");
    delete fmt;
    delete pat;
    delete sym;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestMismatchedCurrencyFormatFail() {
    IcuTestErrorCode status(*this, "TestMismatchedCurrencyFormatFail");
    LocalPointer<DecimalFormat> df(
            dynamic_cast<DecimalFormat*>(DecimalFormat::createCurrencyInstance("en", status)), status);
    if (!assertSuccess("createCurrencyInstance() failed.", status, true, __FILE__, __LINE__)) {return;}
    UnicodeString pattern;
    assertEquals("Test assumes that currency sign is at the beginning",
            u"\u00A4#,##0.00",
            df->toPattern(pattern));
    // Should round-trip on the correct currency format:
    expect2(*df, 1.23, u"\u00A41.23");
    df->setCurrency(u"EUR", status);
    expect2(*df, 1.23, u"\u20AC1.23");
    // Should parse with currency in the wrong place in lenient mode
    df->setLenient(TRUE);
    expect(*df, u"1.23\u20AC", 1.23);
    expectParseCurrency(*df, u"EUR", 1.23, "1.23\\u20AC");
    // Should NOT parse with currency in the wrong place in STRICT mode
    df->setLenient(FALSE);
    {
        Formattable result;
        ErrorCode failStatus;
        df->parse(u"1.23\u20AC", result, failStatus);
        assertEquals("Should fail to parse", U_INVALID_FORMAT_ERROR, failStatus);
    }
    {
        ParsePosition ppos;
        df->parseCurrency(u"1.23\u20AC", ppos);
        assertEquals("Should fail to parse currency", 0, ppos.getIndex());
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestBug9936() {
    UErrorCode status = U_ZERO_ERROR;
    Locale locale("en_US");
    LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
            NumberFormat::createInstance(locale, status)));
    if (U_FAILURE(status)) {
        dataerrln("File %s, Line %d: status = %s.\n", __FILE__, __LINE__, u_errorName(status));
        return;
    }

    if (numberFormat->areSignificantDigitsUsed() == TRUE) {
        errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
    }
    numberFormat->setSignificantDigitsUsed(TRUE);
    if (numberFormat->areSignificantDigitsUsed() == FALSE) {
        errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
    }

    numberFormat->setSignificantDigitsUsed(FALSE);
    if (numberFormat->areSignificantDigitsUsed() == TRUE) {
        errln("File %s, Line %d: areSignificantDigitsUsed() was TRUE, expected FALSE.\n", __FILE__, __LINE__);
    }

    numberFormat->setMinimumSignificantDigits(3);
    if (numberFormat->areSignificantDigitsUsed() == FALSE) {
        errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
    }

    numberFormat->setSignificantDigitsUsed(FALSE);
    numberFormat->setMaximumSignificantDigits(6);
    if (numberFormat->areSignificantDigitsUsed() == FALSE) {
        errln("File %s, Line %d: areSignificantDigitsUsed() was FALSE, expected TRUE.\n", __FILE__, __LINE__);
    }

}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::copyFieldsFrom(const DecimalQuantity& other) {
    bogus = other.bogus;
    lOptPos = other.lOptPos;
    lReqPos = other.lReqPos;
    rReqPos = other.rReqPos;
    rOptPos = other.rOptPos;
    scale = other.scale;
    precision = other.precision;
    flags = other.flags;
    origDouble = other.origDouble;
    origDelta = other.origDelta;
    isApproximate = other.isApproximate;
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::roundToInfinity() {
    if (isApproximate) {
        convertToAccurateDouble();
    }
}

Project: icu
File: numfmtst.cpp

 bool isnan(double x) {
   return _isnan(x);
 }

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCurrencyAmount(void){
    UErrorCode ec = U_ZERO_ERROR;
    static const UChar USD[] = {85, 83, 68, 0}; /*USD*/
    CurrencyAmount ca(9, USD, ec);
    assertSuccess("CurrencyAmount", ec);

    CurrencyAmount ca2(ca);
    if (!(ca2 == ca)){
        errln("CurrencyAmount copy constructed object should be same");
    }

    ca2=ca;
    if (!(ca2 == ca)){
        errln("CurrencyAmount assigned object should be same");
    }

    CurrencyAmount *ca3 = (CurrencyAmount *)ca.clone();
    if (!(*ca3 == ca)){
        errln("CurrencyAmount cloned object should be same");
    }
    delete ca3;
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestDecimalFormatCurrencyParse() {
    // Locale.US
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols* sym = new DecimalFormatSymbols(Locale("en_US"), status);
    if (U_FAILURE(status)) {
        delete sym;
        return;
    }
    UnicodeString pat;
    UChar currency = 0x00A4;
    // "\xA4#,##0.00;-\xA4#,##0.00"
    pat.append(currency).append(currency).append(currency).append("#,##0.00;-").append(currency).append(currency).append(currency).append("#,##0.00");
    DecimalFormat* fmt = new DecimalFormat(pat, sym, status);
    if (U_FAILURE(status)) {
        delete fmt;
        errln("failed to new DecimalFormat in TestDecimalFormatCurrencyParse");
        return;
    }
    const char* DATA[][2] = {
        // the data are:
        // string to be parsed, the parsed result (number)
        {"$1.00", "1"},
        {"USD1.00", "1"},
        {"1.00 US dollar", "1"},
        {"$1,234.56", "1234.56"},
        {"USD1,234.56", "1234.56"},
        {"1,234.56 US dollar", "1234.56"},
    };
    // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
    fmt->setLenient(TRUE);
    for (uint32_t i = 0; i < UPRV_LENGTHOF(DATA); ++i) {
        UnicodeString stringToBeParsed = ctou(DATA[i][0]);
        double parsedResult = atof(DATA[i][1]);
        UErrorCode status = U_ZERO_ERROR;
        Formattable result;
        fmt->parse(stringToBeParsed, result, status);
        logln((UnicodeString)"Input: " + stringToBeParsed + "; output: " + result.getDouble(status));
        if (U_FAILURE(status) ||
            (result.getType() == Formattable::kDouble &&
            result.getDouble() != parsedResult) ||
            (result.getType() == Formattable::kLong &&
            result.getLong() != parsedResult)) {
            errln((UnicodeString)"FAIL parse: Expected " + parsedResult);
        }
    }
    delete fmt;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expectPosition(FieldPosition& pos, int32_t id, int32_t start, int32_t limit,
                                       const UnicodeString& str)  {
  logln(str);
  assertTrue((UnicodeString)"id " + id + " == " + pos.getField(), id == pos.getField());
  assertTrue((UnicodeString)"begin " + start + " == " + pos.getBeginIndex(), start == pos.getBeginIndex());
  assertTrue((UnicodeString)"end " + limit + " == " + pos.getEndIndex(), limit == pos.getEndIndex());
}

Project: icu
File: numfmtst.cpp

const char* attrString(int32_t attrId) {
  switch (attrId) {
    case UNUM_INTEGER_FIELD: return "integer";
    case UNUM_FRACTION_FIELD: return "fraction";
    case UNUM_DECIMAL_SEPARATOR_FIELD: return "decimal separator";
    case UNUM_EXPONENT_SYMBOL_FIELD: return "exponent symbol";
    case UNUM_EXPONENT_SIGN_FIELD: return "exponent sign";
    case UNUM_EXPONENT_FIELD: return "exponent";
    case UNUM_GROUPING_SEPARATOR_FIELD: return "grouping separator";
    case UNUM_CURRENCY_FIELD: return "currency";
    case UNUM_PERCENT_FIELD: return "percent";
    case UNUM_PERMILL_FIELD: return "permille";
    case UNUM_SIGN_FIELD: return "sign";
    default: return "";
  }
}

Project: icu
File: fmtable.cpp

Formattable::~Formattable()
{
    dispose();
}

Project: icu
File: numfmtst.cpp

static void parseCurrencyAmount(const UnicodeString& str,
                                const NumberFormat& fmt,
                                UChar delim,
                                Formattable& result,
                                UErrorCode& ec) {
    UnicodeString num, cur;
    int32_t i = str.indexOf(delim);
    str.extractBetween(0, i, num);
    str.extractBetween(i+1, INT32_MAX, cur);
    Formattable n;
    fmt.parse(num, n, ec);
    result.adoptObject(new CurrencyAmount(n, cur.getTerminatedBuffer(), ec));
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expect_rbnf(NumberFormat& fmt, const Formattable& n,
                              const UnicodeString& exp, UBool rt) {
    UnicodeString saw;
    FieldPosition pos;
    UErrorCode status = U_ZERO_ERROR;
    fmt.format(n, saw, pos, status);
    CHECK(status, "NumberFormat::format");
    if (saw == exp) {
        logln(UnicodeString("Ok   ") + toString(n) +
              " = \"" +
              escape(saw) + "\"");
        // We should be able to round-trip the formatted string =>
        // number => string (but not the other way around: number
        // => string => number2, might have number2 != number):
        if (rt) {
            Formattable n2;
            fmt.parse(exp, n2, status);
            if (U_FAILURE(status)) {
                errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\"");
                return;
            }
            UnicodeString saw2;
            fmt.format(n2, saw2, pos, status);
            CHECK(status, "NumberFormat::format");
            if (saw2 != exp) {
                errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
                      " => \"" + saw2 + "\"");
            }
        }
    } else {
        errln(UnicodeString("FAIL ") + toString(n) +
              " = \"" +
              escape(saw) + "\", expected \"" + exp + "\"");
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCurrencyUsage() {
    double agent = 123.567;

    UErrorCode status;
    DecimalFormat *fmt;

    // compare the Currency and Currency Cash Digits
    // Note that as of CLDR 26:
    // * TWD and PKR switched from 0 decimals to 2; ISK still has 0, so change test to that
    // * CAD rounds to .05 in cash mode only
    // 1st time for getter/setter, 2nd time for factory method
    Locale enUS_ISK("en_US@currency=ISK");

    for(int i=0; i<2; i++){
        status = U_ZERO_ERROR;
        if(i == 0){
            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CURRENCY, status);
            if (assertSuccess("en_US@currency=ISK/CURRENCY", status, TRUE) == FALSE) {
                continue;
            }

            UnicodeString original;
            fmt->format(agent,original);
            assertEquals("Test Currency Usage 1", u"ISK\u00A0124", original);

            // test the getter here
            UCurrencyUsage curUsage = fmt->getCurrencyUsage();
            assertEquals("Test usage getter - standard", (int32_t)curUsage, (int32_t)UCURR_USAGE_STANDARD);

            fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
        }else{
            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_ISK, UNUM_CASH_CURRENCY, status);
            if (assertSuccess("en_US@currency=ISK/CASH", status, TRUE) == FALSE) {
                continue;
            }
        }

        // must be usage = cash
        UCurrencyUsage curUsage = fmt->getCurrencyUsage();
        assertEquals("Test usage getter - cash", (int32_t)curUsage, (int32_t)UCURR_USAGE_CASH);

        UnicodeString cash_currency;
        fmt->format(agent,cash_currency);
        assertEquals("Test Currency Usage 2", u"ISK\u00A0124", cash_currency);
        delete fmt;
    }

    // compare the Currency and Currency Cash Rounding
    // 1st time for getter/setter, 2nd time for factory method
    Locale enUS_CAD("en_US@currency=CAD");
    for(int i=0; i<2; i++){
        status = U_ZERO_ERROR;
        if(i == 0){
            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
            if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
                continue;
            }

            UnicodeString original_rounding;
            fmt->format(agent, original_rounding);
            assertEquals("Test Currency Usage 3", u"CA$123.57", original_rounding);
            fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
        }else{
            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
            if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
                continue;
            }
        }

        UnicodeString cash_rounding_currency;
        fmt->format(agent, cash_rounding_currency);
        assertEquals("Test Currency Usage 4", u"CA$123.55", cash_rounding_currency);
        delete fmt;
    }

    // Test the currency change
    // 1st time for getter/setter, 2nd time for factory method
    const UChar CUR_PKR[] = {0x50, 0x4B, 0x52, 0};
    for(int i=0; i<2; i++){
        status = U_ZERO_ERROR;
        if(i == 0){
            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CURRENCY, status);
            if (assertSuccess("en_US@currency=CAD/CURRENCY", status, TRUE) == FALSE) {
                continue;
            }
            fmt->setCurrencyUsage(UCURR_USAGE_CASH, &status);
        }else{
            fmt = (DecimalFormat *) NumberFormat::createInstance(enUS_CAD, UNUM_CASH_CURRENCY, status);
            if (assertSuccess("en_US@currency=CAD/CASH", status, TRUE) == FALSE) {
                continue;
            }
        }

        UnicodeString cur_original;
        fmt->setCurrencyUsage(UCURR_USAGE_STANDARD, &status);
        fmt->format(agent, cur_original);
        assertEquals("Test Currency Usage 5", u"CA$123.57", cur_original);

        fmt->setCurrency(CUR_PKR, status);
        assertSuccess("Set currency to PKR", status);

        UnicodeString PKR_changed;
        fmt->format(agent, PKR_changed);
        assertEquals("Test Currency Usage 6", u"PKR\u00A0123.57", PKR_changed);
        delete fmt;
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestNumberingSystems() {

    const TestNumberingSystemItem DATA[] = {
        { "en_US@numbers=thai", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" },
        { "en_US@numbers=hebr", 5678.0, TRUE, "\\u05D4\\u05F3\\u05EA\\u05E8\\u05E2\\u05F4\\u05D7" },
        { "en_US@numbers=arabext", 1234.567, FALSE, "\\u06F1\\u066c\\u06F2\\u06F3\\u06F4\\u066b\\u06F5\\u06F6\\u06F7" },
        { "ar_EG", 1234.567, FALSE, "\\u0661\\u066C\\u0662\\u0663\\u0664\\u066b\\u0665\\u0666\\u0667" },
        { "th_TH@numbers=traditional", 1234.567, FALSE, "\\u0E51,\\u0E52\\u0E53\\u0E54.\\u0E55\\u0E56\\u0E57" }, // fall back to native per TR35
        { "ar_MA", 1234.567, FALSE, "1.234,567" },
        { "en_US@numbers=hanidec", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
        { "ta_IN@numbers=native", 1234.567, FALSE, "\\u0BE7,\\u0BE8\\u0BE9\\u0BEA.\\u0BEB\\u0BEC\\u0BED" },
        { "ta_IN@numbers=traditional", 1235.0, TRUE, "\\u0BF2\\u0BE8\\u0BF1\\u0BE9\\u0BF0\\u0BEB" },
        { "ta_IN@numbers=finance", 1234.567, FALSE, "1,234.567" }, // fall back to default per TR35
        { "zh_TW@numbers=native", 1234.567, FALSE, "\\u4e00,\\u4e8c\\u4e09\\u56db.\\u4e94\\u516d\\u4e03" },
        { "zh_TW@numbers=traditional", 1234.567, TRUE, "\\u4E00\\u5343\\u4E8C\\u767E\\u4E09\\u5341\\u56DB\\u9EDE\\u4E94\\u516D\\u4E03" },
        { "zh_TW@numbers=finance", 1234.567, TRUE, "\\u58F9\\u4EDF\\u8CB3\\u4F70\\u53C3\\u62FE\\u8086\\u9EDE\\u4F0D\\u9678\\u67D2" },
        { NULL, 0, FALSE, NULL }
    };

    UErrorCode ec;

    const TestNumberingSystemItem *item;
    for (item = DATA; item->localeName != NULL; item++) {
        ec = U_ZERO_ERROR;
        Locale loc = Locale::createFromName(item->localeName);

        NumberFormat *origFmt = NumberFormat::createInstance(loc,ec);
        if (U_FAILURE(ec)) {
            dataerrln("FAIL: getInstance(%s) - %s", item->localeName, u_errorName(ec));
            continue;
        }
        // Clone to test ticket #10682
        NumberFormat *fmt = (NumberFormat *) origFmt->clone();
        delete origFmt;


        if (item->isRBNF) {
            expect3(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
        } else {
            expect2(*fmt,item->value,CharsToUnicodeString(item->expectedResult));
        }
        delete fmt;
    }


    // Test bogus keyword value
    ec = U_ZERO_ERROR;
    Locale loc4 = Locale::createFromName("en_US@numbers=foobar");
    NumberFormat* fmt4= NumberFormat::createInstance(loc4, ec);
    if ( ec != U_UNSUPPORTED_ERROR ) {
        errln("FAIL: getInstance(en_US@numbers=foobar) should have returned U_UNSUPPORTED_ERROR");
        delete fmt4;
    }

    ec = U_ZERO_ERROR;
    NumberingSystem *ns = NumberingSystem::createInstance(ec);
    if (U_FAILURE(ec)) {
        dataerrln("FAIL: NumberingSystem::createInstance(ec); - %s", u_errorName(ec));
    }

    if ( ns != NULL ) {
        ns->getDynamicClassID();
        ns->getStaticClassID();
    } else {
        errln("FAIL: getInstance() returned NULL.");
    }

    NumberingSystem *ns1 = new NumberingSystem(*ns);
    if (ns1 == NULL) {
        errln("FAIL: NumberSystem copy constructor returned NULL.");
    }

    delete ns1;
    delete ns;

}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::multiplyBy(const DecNum& multiplicand, UErrorCode& status) {
    if (isInfinite() || isZero() || isNaN()) {
        return;
    }
    // Convert to DecNum, multiply, and convert back.
    DecNum decnum;
    toDecNum(decnum, status);
    if (U_FAILURE(status)) { return; }
    decnum.multiplyBy(multiplicand, status);
    if (U_FAILURE(status)) { return; }
    setToDecNum(decnum, status);
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::roundToMagnitude(int32_t magnitude, RoundingMode roundingMode, bool nickel, UErrorCode& status) {
    // The position in the BCD at which rounding will be performed; digits to the right of position
    // will be rounded away.
    int position = safeSubtract(magnitude, scale);

    // "trailing" = least significant digit to the left of rounding
    int8_t trailingDigit = getDigitPos(position);

    if (position <= 0 && !isApproximate && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
        // All digits are to the left of the rounding magnitude.
    } else if (precision == 0) {
        // No rounding for zero.
    } else {
        // Perform rounding logic.
        // "leading" = most significant digit to the right of rounding
        int8_t leadingDigit = getDigitPos(safeSubtract(position, 1));

        // Compute which section of the number we are in.
        // EDGE means we are at the bottom or top edge, like 1.000 or 1.999 (used by doubles)
        // LOWER means we are between the bottom edge and the midpoint, like 1.391
        // MIDPOINT means we are exactly in the middle, like 1.500
        // UPPER means we are between the midpoint and the top edge, like 1.916
        roundingutils::Section section;
        if (!isApproximate) {
            if (nickel && trailingDigit != 2 && trailingDigit != 7) {
                // Nickel rounding, and not at .02x or .07x
                if (trailingDigit < 2) {
                    // .00, .01 => down to .00
                    section = roundingutils::SECTION_LOWER;
                } else if (trailingDigit < 5) {
                    // .03, .04 => up to .05
                    section = roundingutils::SECTION_UPPER;
                } else if (trailingDigit < 7) {
                    // .05, .06 => down to .05
                    section = roundingutils::SECTION_LOWER;
                } else {
                    // .08, .09 => up to .10
                    section = roundingutils::SECTION_UPPER;
                }
            } else if (leadingDigit < 5) {
                // Includes nickel rounding .020-.024 and .070-.074
                section = roundingutils::SECTION_LOWER;
            } else if (leadingDigit > 5) {
                // Includes nickel rounding .026-.029 and .076-.079
                section = roundingutils::SECTION_UPPER;
            } else {
                // Includes nickel rounding .025 and .075
                section = roundingutils::SECTION_MIDPOINT;
                for (int p = safeSubtract(position, 2); p >= 0; p--) {
                    if (getDigitPos(p) != 0) {
                        section = roundingutils::SECTION_UPPER;
                        break;
                    }
                }
            }
        } else {
            int32_t p = safeSubtract(position, 2);
            int32_t minP = uprv_max(0, precision - 14);
            if (leadingDigit == 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
                section = roundingutils::SECTION_LOWER_EDGE;
                for (; p >= minP; p--) {
                    if (getDigitPos(p) != 0) {
                        section = roundingutils::SECTION_LOWER;
                        break;
                    }
                }
            } else if (leadingDigit == 4 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
                section = roundingutils::SECTION_MIDPOINT;
                for (; p >= minP; p--) {
                    if (getDigitPos(p) != 9) {
                        section = roundingutils::SECTION_LOWER;
                        break;
                    }
                }
            } else if (leadingDigit == 5 && (!nickel || trailingDigit == 2 || trailingDigit == 7)) {
                section = roundingutils::SECTION_MIDPOINT;
                for (; p >= minP; p--) {
                    if (getDigitPos(p) != 0) {
                        section = roundingutils::SECTION_UPPER;
                        break;
                    }
                }
            } else if (leadingDigit == 9 && (!nickel || trailingDigit == 4 || trailingDigit == 9)) {
                section = roundingutils::SECTION_UPPER_EDGE;
                for (; p >= minP; p--) {
                    if (getDigitPos(p) != 9) {
                        section = roundingutils::SECTION_UPPER;
                        break;
                    }
                }
            } else if (nickel && trailingDigit != 2 && trailingDigit != 7) {
                // Nickel rounding, and not at .02x or .07x
                if (trailingDigit < 2) {
                    // .00, .01 => down to .00
                    section = roundingutils::SECTION_LOWER;
                } else if (trailingDigit < 5) {
                    // .03, .04 => up to .05
                    section = roundingutils::SECTION_UPPER;
                } else if (trailingDigit < 7) {
                    // .05, .06 => down to .05
                    section = roundingutils::SECTION_LOWER;
                } else {
                    // .08, .09 => up to .10
                    section = roundingutils::SECTION_UPPER;
                }
            } else if (leadingDigit < 5) {
                // Includes nickel rounding .020-.024 and .070-.074
                section = roundingutils::SECTION_LOWER;
            } else {
                // Includes nickel rounding .026-.029 and .076-.079
                section = roundingutils::SECTION_UPPER;
            }

            bool roundsAtMidpoint = roundingutils::roundsAtMidpoint(roundingMode);
            if (safeSubtract(position, 1) < precision - 14 ||
                (roundsAtMidpoint && section == roundingutils::SECTION_MIDPOINT) ||
                (!roundsAtMidpoint && section < 0 /* i.e. at upper or lower edge */)) {
                // Oops! This means that we have to get the exact representation of the double,
                // because the zone of uncertainty is along the rounding boundary.
                convertToAccurateDouble();
                roundToMagnitude(magnitude, roundingMode, nickel, status); // start over
                return;
            }

            // Turn off the approximate double flag, since the value is now confirmed to be exact.
            isApproximate = false;
            origDouble = 0.0;
            origDelta = 0;

            if (position <= 0 && (!nickel || trailingDigit == 0 || trailingDigit == 5)) {
                // All digits are to the left of the rounding magnitude.
                return;
            }

            // Good to continue rounding.
            if (section == -1) { section = roundingutils::SECTION_LOWER; }
            if (section == -2) { section = roundingutils::SECTION_UPPER; }
        }

        // Nickel rounding "half even" goes to the nearest whole (away from the 5).
        bool isEven = nickel
                ? (trailingDigit < 2 || trailingDigit > 7
                        || (trailingDigit == 2 && section != roundingutils::SECTION_UPPER)
                        || (trailingDigit == 7 && section == roundingutils::SECTION_UPPER))
                : (trailingDigit % 2) == 0;

        bool roundDown = roundingutils::getRoundingDirection(isEven,
                isNegative(),
                section,
                roundingMode,
                status);
        if (U_FAILURE(status)) {
            return;
        }

        // Perform truncation
        if (position >= precision) {
            setBcdToZero();
            scale = magnitude;
        } else {
            shiftRight(position);
        }

        if (nickel) {
            if (trailingDigit < 5 && roundDown) {
                setDigitPos(0, 0);
                compact();
                return;
            } else if (trailingDigit >= 5 && !roundDown) {
                setDigitPos(0, 9);
                trailingDigit = 9;
                // do not return: use the bubbling logic below
            } else {
                setDigitPos(0, 5);
                // compact not necessary: digit at position 0 is nonzero
                return;
            }
        }

        // Bubble the result to the higher digits
        if (!roundDown) {
            if (trailingDigit == 9) {
                int bubblePos = 0;
                // Note: in the long implementation, the most digits BCD can have at this point is
                // 15, so bubblePos <= 15 and getDigitPos(bubblePos) is safe.
                for (; getDigitPos(bubblePos) == 9; bubblePos++) {}
                shiftRight(bubblePos); // shift off the trailing 9s
            }
            int8_t digit0 = getDigitPos(0);
            U_ASSERT(digit0 != 9);
            setDigitPos(0, static_cast<int8_t>(digit0 + 1));
            precision += 1; // in case an extra digit got added
        }

        compact();
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::checkRounding(DecimalFormat* df, double base, int iterations, double increment) {
    df->setRoundingIncrement(increment);
    double lastParsed=INT32_MIN; //Intger.MIN_VALUE
    for (int i=-iterations; i<=iterations;i++) {
        double iValue=base+(increment*(i*0.1));
        double smallIncrement=0.00000001;
        if (iValue!=0) {
            smallIncrement*=iValue;
        }
        //we not only test the value, but some values in a small range around it
        lastParsed=checkRound(df, iValue-smallIncrement, lastParsed);
        lastParsed=checkRound(df, iValue, lastParsed);
        lastParsed=checkRound(df, iValue+smallIncrement, lastParsed);
    }
}

Project: icu
File: fmtable.cpp

Formattable::isNumeric() const {
    switch (fType) {
    case kDouble:
    case kLong:
    case kInt64:
        return TRUE;
    default:
        return FALSE;
    }
}

Project: icu
File: number_decimalquantity.cpp

uint64_t DecimalQuantity::toFractionLong(bool includeTrailingZeros) const {
    uint64_t result = 0L;
    int32_t magnitude = -1;
    int32_t lowerMagnitude = std::max(scale, rOptPos);
    if (includeTrailingZeros) {
        lowerMagnitude = std::min(lowerMagnitude, rReqPos);
    }
    for (; magnitude >= lowerMagnitude && result <= 1e18L; magnitude--) {
        result = result * 10 + getDigitPos(magnitude - scale);
    }
    // Remove trailing zeros; this can happen during integer overflow cases.
    if (!includeTrailingZeros) {
        while (result > 0 && (result % 10) == 0) {
            result /= 10;
        }
    }
    return result;
}

Project: icu
File: fmtable.cpp

Formattable::getBogus() const 
{
    return (UnicodeString*)&fBogus; /* cast away const :-( */
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestAPI(void)
{
  logln("Test API");
  UErrorCode status = U_ZERO_ERROR;
  NumberFormat *test = NumberFormat::createInstance("root", status);
  if(U_FAILURE(status)) {
    dataerrln("unable to create format object - %s", u_errorName(status));
  }
  if(test != NULL) {
    test->setMinimumIntegerDigits(10);
    test->setMaximumIntegerDigits(1);

    test->setMinimumFractionDigits(10);
    test->setMaximumFractionDigits(1);

    UnicodeString result;
    FieldPosition pos;
    Formattable bla("Paja Patak"); // Donald Duck for non Serbian speakers
    test->format(bla, result, pos, status);
    if(U_SUCCESS(status)) {
      errln("Yuck... Formatted a duck... As a number!");
    } else {
      status = U_ZERO_ERROR;
    }

    result.remove();
    int64_t ll = 12;
    test->format(ll, result);
    assertEquals("format int64_t error", u"2.0", result);

    test->setMinimumIntegerDigits(4);
    test->setMinimumFractionDigits(4);

    result.remove();
    test->format(ll, result);
    assertEquals("format int64_t error", u"0,012.0000", result);

    ParsePosition ppos;
    LocalPointer<CurrencyAmount> currAmt(test->parseCurrency("",ppos));
    // old test for (U_FAILURE(status)) was bogus here, method does not set status!
    if (ppos.getIndex()) {
        errln("Parsed empty string as currency");
    }

    delete test;
  }
}

Project: icu
File: number_decimalquantity.cpp

bool DecimalQuantity::isNaN() const {
    return (flags & NAN_FLAG) != 0;
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestPatterns(void)
{
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols sym(Locale::getUS(), status);
    if (U_FAILURE(status)) { errcheckln(status, "FAIL: Could not construct DecimalFormatSymbols - %s", u_errorName(status)); return; }

    const char* pat[]    = { "#.#", "#.", ".#", "#" };
    int32_t pat_length = UPRV_LENGTHOF(pat);
    const char* newpat[] = { "0.#", "0.", "#.0", "0" };
    const char* num[]    = { "0",   "0.", ".0", "0" };
    for (int32_t i=0; i<pat_length; ++i)
    {
        status = U_ZERO_ERROR;
        DecimalFormat fmt(pat[i], sym, status);
        if (U_FAILURE(status)) { errln((UnicodeString)"FAIL: DecimalFormat constructor failed for " + pat[i]); continue; }
        UnicodeString newp; fmt.toPattern(newp);
        if (!(newp == newpat[i]))
            errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
                  "; " + newp + " seen instead");

        UnicodeString s; (*(NumberFormat*)&fmt).format((int32_t)0, s);
        if (!(s == num[i]))
        {
            errln((UnicodeString)"FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
                  "; " + s + " seen instead");
            logln((UnicodeString)"Min integer digits = " + fmt.getMinimumIntegerDigits());
        }
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expect3(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
    // Don't round-trip format test, since we explicitly do it
    expect_rbnf(fmt, n, str, FALSE);
    expect_rbnf(fmt, str, n);
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestScientificGrouping() {
    // jb 2552
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormat fmt("##0.00E0",status);
    if (assertSuccess("", status, true, __FILE__, __LINE__)) {
        expect(fmt, .01234, "12.3E-3");
        expect(fmt, .1234, "123E-3");
        expect(fmt, 1.234, "1.23E0");
        expect(fmt, 12.34, "12.3E0");
        expect(fmt, 123.4, "123E0");
        expect(fmt, 1234., "1.23E3");
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::verifyFieldPositionIterator(
        NumberFormatTest_Attributes *expected, FieldPositionIterator &iter) {
    int32_t idx = 0;
    FieldPosition fp;
    while (iter.next(fp)) {
        if (expected[idx].spos == -1) {
            errln("Iterator should have ended. got %d", fp.getField());
            return;
        }
        assertEquals("id", expected[idx].id, fp.getField());
        assertEquals("start", expected[idx].spos, fp.getBeginIndex());
        assertEquals("end", expected[idx].epos, fp.getEndIndex());
        ++idx;
    }
    if (expected[idx].spos != -1) {
        errln("Premature end of iterator. expected %d", expected[idx].id);
    }
}

Project: icu
File: fmtable.cpp

Formattable::getLong(UErrorCode& status) const
{
    if (U_FAILURE(status)) {
        return 0;
    }
        
    switch (fType) {
    case Formattable::kLong: 
        return (int32_t)fValue.fInt64;
    case Formattable::kInt64:
        if (fValue.fInt64 > INT32_MAX) {
            status = U_INVALID_FORMAT_ERROR;
            return INT32_MAX;
        } else if (fValue.fInt64 < INT32_MIN) {
            status = U_INVALID_FORMAT_ERROR;
            return INT32_MIN;
        } else {
            return (int32_t)fValue.fInt64;
        }
    case Formattable::kDouble:
        if (fValue.fDouble > INT32_MAX) {
            status = U_INVALID_FORMAT_ERROR;
            return INT32_MAX;
        } else if (fValue.fDouble < INT32_MIN) {
            status = U_INVALID_FORMAT_ERROR;
            return INT32_MIN;
        } else {
            return (int32_t)fValue.fDouble; // loses fraction
        }
    case Formattable::kObject:
        if (fValue.fObject == NULL) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return 0;
        }
        // TODO Later replace this with instanceof call
        if (instanceOfMeasure(fValue.fObject)) {
            return ((const Measure*) fValue.fObject)->
                getNumber().getLong(status);
        }
        U_FALLTHROUGH;
    default:
        status = U_INVALID_FORMAT_ERROR;
        return 0;
    }
}

Project: icu
File: fmtable.cpp

StringPiece Formattable::getDecimalNumber(UErrorCode &status) {
    if (U_FAILURE(status)) {
        return "";
    }
    if (fDecimalStr != NULL) {
      return fDecimalStr->toStringPiece();
    }

    CharString *decimalStr = internalGetCharString(status);
    if(decimalStr == NULL) {
      return ""; // getDecimalNumber returns "" for error cases
    } else {
      return decimalStr->toStringPiece();
    }
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::ensureCapacity() {
    ensureCapacity(40);
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::roundingTest(NumberFormat& nf, double x, int32_t maxFractionDigits, const char* expected)
{
    nf.setMaximumFractionDigits(maxFractionDigits);
    UnicodeString out; nf.format(x, out);
    logln((UnicodeString)"" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
    if (!(out==expected)) errln((UnicodeString)"FAIL: Expected " + expected);
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestCurrencyFormatForMixParsing() {
    UErrorCode status = U_ZERO_ERROR;
    MeasureFormat* curFmt = MeasureFormat::createCurrencyFormat(Locale("en_US"), status);
    if (U_FAILURE(status)) {
        delete curFmt;
        return;
    }
    const char* formats[] = {
        "$1,234.56",  // string to be parsed
        "USD1,234.56",
        "US dollars1,234.56",
        // "1,234.56 US dollars" // Fails in 62 because currency format is not compatible with pattern.
    };
    const CurrencyAmount* curramt = NULL;
    for (uint32_t i = 0; i < UPRV_LENGTHOF(formats); ++i) {
        UnicodeString stringToBeParsed = ctou(formats[i]);
        logln(UnicodeString("stringToBeParsed: ") + stringToBeParsed);
        Formattable result;
        UErrorCode status = U_ZERO_ERROR;
        curFmt->parseObject(stringToBeParsed, result, status);
        if (U_FAILURE(status)) {
          errln("FAIL: measure format parsing: '%s' ec: %s", formats[i], u_errorName(status));
        } else if (result.getType() != Formattable::kObject ||
            (curramt = dynamic_cast<const CurrencyAmount*>(result.getObject())) == NULL ||
            curramt->getNumber().getDouble() != 1234.56 ||
            UnicodeString(curramt->getISOCurrency()).compare(ISO_CURRENCY_USD)
        ) {
            errln("FAIL: getCurrencyFormat of default locale (en_US) failed roundtripping the number ");
            if (curramt->getNumber().getDouble() != 1234.56) {
                errln((UnicodeString)"wong number, expect: 1234.56" + ", got: " + curramt->getNumber().getDouble());
            }
            if (curramt->getISOCurrency() != ISO_CURRENCY_USD) {
                errln((UnicodeString)"wong currency, expect: USD" + ", got: " + curramt->getISOCurrency());
            }
        }
    }
    delete curFmt;
}

Project: icu
File: number_decimalquantity.cpp

bool DecimalQuantity::isNegative() const {
    return (flags & NEGATIVE_FLAG) != 0;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11649_DecFmtCurrencies() {
    IcuTestErrorCode status(*this, "Test11649_DecFmtCurrencies");
    UnicodeString pattern("\\u00a4\\u00a4\\u00a4 0.00");
    pattern = pattern.unescape();
    DecimalFormat fmt(pattern, status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    static const UChar USD[] = u"USD";
    fmt.setCurrency(USD);
    UnicodeString appendTo;

    assertEquals("", "US dollars 12.34", fmt.format(12.34, appendTo));
    UnicodeString topattern;

    assertEquals("", pattern, fmt.toPattern(topattern));
    DecimalFormat fmt2(topattern, status);
    fmt2.setCurrency(USD);

    appendTo.remove();
    assertEquals("", "US dollars 12.34", fmt2.format(12.34, appendTo));
}

Project: icu
File: numfmtst.cpp

    virtual Format* clone() const {return NULL;}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestLenientParse(void)
{
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormat *format = new DecimalFormat("(#,##0)", status);
    Formattable n;

    if (format == NULL || U_FAILURE(status)) {
        dataerrln("Unable to create DecimalFormat (#,##0) - %s", u_errorName(status));
    } else {
        format->setLenient(TRUE);
        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientAffixTestCases); t += 1) {
        	UnicodeString testCase = ctou(lenientAffixTestCases[t]);

            format->parse(testCase, n, status);
            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());

            if (U_FAILURE(status) || n.getType() != Formattable::kLong ||
            	n.getLong() != 1) {
            	dataerrln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientAffixTestCases[t]
                      + (UnicodeString) "\"; error code = " + u_errorName(status));
            	status = U_ZERO_ERROR;
            }
       }
       delete format;
    }

    Locale en_US("en_US");
    Locale sv_SE("sv_SE");

    NumberFormat *mFormat = NumberFormat::createInstance(sv_SE, UNUM_DECIMAL, status);

    if (mFormat == NULL || U_FAILURE(status)) {
        dataerrln("Unable to create NumberFormat (sv_SE, UNUM_DECIMAL) - %s", u_errorName(status));
    } else {
        mFormat->setLenient(TRUE);
        for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
            UnicodeString testCase = ctou(lenientMinusTestCases[t]);

            mFormat->parse(testCase, n, status);
            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());

            if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
                errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
                      + (UnicodeString) "\"; error code = " + u_errorName(status));
                status = U_ZERO_ERROR;
            }
        }
        delete mFormat;
    }

    mFormat = NumberFormat::createInstance(en_US, UNUM_DECIMAL, status);

    if (mFormat == NULL || U_FAILURE(status)) {
        dataerrln("Unable to create NumberFormat (en_US, UNUM_DECIMAL) - %s", u_errorName(status));
    } else {
        mFormat->setLenient(TRUE);
        for (int32_t t = 0; t < UPRV_LENGTHOF(lenientMinusTestCases); t += 1) {
            UnicodeString testCase = ctou(lenientMinusTestCases[t]);

            mFormat->parse(testCase, n, status);
            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());

            if (U_FAILURE(status) || n.getType() != Formattable::kLong || n.getLong() != -5) {
                errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientMinusTestCases[t]
                      + (UnicodeString) "\"; error code = " + u_errorName(status));
                status = U_ZERO_ERROR;
            }
        }
        delete mFormat;
    }

    NumberFormat *cFormat = NumberFormat::createInstance(en_US, UNUM_CURRENCY, status);

    if (cFormat == NULL || U_FAILURE(status)) {
        dataerrln("Unable to create NumberFormat (en_US, UNUM_CURRENCY) - %s", u_errorName(status));
    } else {
        cFormat->setLenient(TRUE);
        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientCurrencyTestCases); t += 1) {
        	UnicodeString testCase = ctou(lenientCurrencyTestCases[t]);

            cFormat->parse(testCase, n, status);
            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());

            if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
            	n.getLong() != 1000) {
            	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientCurrencyTestCases[t]
                      + (UnicodeString) "\"; error code = " + u_errorName(status));
            	status = U_ZERO_ERROR;
            }
        }

        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativeCurrencyTestCases); t += 1) {
        	UnicodeString testCase = ctou(lenientNegativeCurrencyTestCases[t]);

            cFormat->parse(testCase, n, status);
            logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());

            if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
            	n.getLong() != -1000) {
            	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativeCurrencyTestCases[t]
                      + (UnicodeString) "\"; error code = " + u_errorName(status));
            	status = U_ZERO_ERROR;
            }
        }

        delete cFormat;
    }

    NumberFormat *pFormat = NumberFormat::createPercentInstance(en_US, status);

    if (pFormat == NULL || U_FAILURE(status)) {
        dataerrln("Unable to create NumberFormat::createPercentInstance (en_US) - %s", u_errorName(status));
    } else {
        pFormat->setLenient(TRUE);
        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientPercentTestCases); t += 1) {
        	UnicodeString testCase = ctou(lenientPercentTestCases[t]);

        	pFormat->parse(testCase, n, status);
            logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());

            if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
            	n.getDouble() != 0.25) {
            	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientPercentTestCases[t]
                      + (UnicodeString) "\"; error code = " + u_errorName(status)
                      + "; got: " + n.getDouble(status));
            	status = U_ZERO_ERROR;
            }
        }

        for (int32_t t = 0; t < UPRV_LENGTHOF (lenientNegativePercentTestCases); t += 1) {
        	UnicodeString testCase = ctou(lenientNegativePercentTestCases[t]);

        	pFormat->parse(testCase, n, status);
            logln((UnicodeString)"parse(" + testCase + ") = " + n.getDouble());

            if (U_FAILURE(status) ||n.getType() != Formattable::kDouble ||
            	n.getDouble() != -0.25) {
            	errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) lenientNegativePercentTestCases[t]
                      + (UnicodeString) "\"; error code = " + u_errorName(status)
                      + "; got: " + n.getDouble(status));
            	status = U_ZERO_ERROR;
            }
        }

        delete pFormat;
    }

   // Test cases that should fail with a strict parse and pass with a
   // lenient parse.
   NumberFormat *nFormat = NumberFormat::createInstance(en_US, status);

   if (nFormat == NULL || U_FAILURE(status)) {
       dataerrln("Unable to create NumberFormat (en_US) - %s", u_errorName(status));
   } else {
       // first, make sure that they fail with a strict parse
       for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
	       UnicodeString testCase = ctou(strictFailureTestCases[t]);

	       nFormat->parse(testCase, n, status);
	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());

	       if (! U_FAILURE(status)) {
		       errln((UnicodeString)"Strict Parse succeeded for \"" + (UnicodeString) strictFailureTestCases[t]
                     + (UnicodeString) "\"; error code = " + u_errorName(status));
	       }

	       status = U_ZERO_ERROR;
       }

       // then, make sure that they pass with a lenient parse
       nFormat->setLenient(TRUE);
       for (int32_t t = 0; t < UPRV_LENGTHOF(strictFailureTestCases); t += 1) {
	       UnicodeString testCase = ctou(strictFailureTestCases[t]);

	       nFormat->parse(testCase, n, status);
	       logln((UnicodeString)"parse(" + testCase + ") = " + n.getLong());

	       if (U_FAILURE(status) ||n.getType() != Formattable::kLong ||
	            	n.getLong() != 1000) {
		       errln((UnicodeString)"Lenient parse failed for \"" + (UnicodeString) strictFailureTestCases[t]
                     + (UnicodeString) "\"; error code = " + u_errorName(status));
		       status = U_ZERO_ERROR;
	       }
       }

       delete nFormat;
   }
}

Project: icu
File: number_decimalquantity.cpp

DecimalQuantity::DecimalQuantity() {
    setBcdToZero();
    flags = 0;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expectPositions(FieldPositionIterator& iter, int32_t *values, int32_t tupleCount,
                                       const UnicodeString& str)  {
  UBool found[10];
  FieldPosition fp;

  if (tupleCount > 10) {
    assertTrue("internal error, tupleCount too large", FALSE);
  } else {
    for (int i = 0; i < tupleCount; ++i) {
      found[i] = FALSE;
    }
  }

  logln(str);
  while (iter.next(fp)) {
    UBool ok = FALSE;
    int32_t id = fp.getField();
    int32_t start = fp.getBeginIndex();
    int32_t limit = fp.getEndIndex();

    // is there a logln using printf?
    char buf[128];
    sprintf(buf, "%24s %3d %3d %3d", attrString(id), id, start, limit);
    logln(buf);

    for (int i = 0; i < tupleCount; ++i) {
      if (found[i]) {
        continue;
      }
      if (values[i*3] == id &&
          values[i*3+1] == start &&
          values[i*3+2] == limit) {
        found[i] = ok = TRUE;
        break;
      }
    }

    assertTrue((UnicodeString)"found [" + id + "," + start + "," + limit + "]", ok);
  }

  // check that all were found
  UBool ok = TRUE;
  for (int i = 0; i < tupleCount; ++i) {
    if (!found[i]) {
      ok = FALSE;
      assertTrue((UnicodeString) "missing [" + values[i*3] + "," + values[i*3+1] + "," + values[i*3+2] + "]", found[i]);
    }
  }
  assertTrue("no expected values were missing", ok);
}

Project: icu
File: numfmtst.cpp

static int32_t keywordIndex(const UnicodeString& tok) {
    for (int32_t i=0; KEYWORDS[i]!=0; ++i) {
        if (tok==KEYWORDS[i]) {
            return i;
        }
    }
    return -1;
}

Project: icu
File: fmtable.cpp

Formattable::Formattable(int64_t value)
{
    init();
    fType = kInt64;
    fValue.fInt64 = value;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11645_ApplyPatternEquality() {
    IcuTestErrorCode status(*this, "Test11645_ApplyPatternEquality");
    const char16_t* pattern = u"#,##0.0#";
    LocalPointer<DecimalFormat> fmt((DecimalFormat*) NumberFormat::createInstance(status), status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    fmt->applyPattern(pattern, status);
    LocalPointer<DecimalFormat> fmtCopy;

    static const int32_t newMultiplier = 37;
    fmtCopy.adoptInstead(new DecimalFormat(*fmt));
    assertFalse("Value before setter", fmtCopy->getMultiplier() == newMultiplier);
    fmtCopy->setMultiplier(newMultiplier);
    assertEquals("Value after setter", fmtCopy->getMultiplier(), newMultiplier);
    fmtCopy->applyPattern(pattern, status);
    assertEquals("Value after applyPattern", fmtCopy->getMultiplier(), newMultiplier);
    assertFalse("multiplier", *fmt == *fmtCopy);

    static const NumberFormat::ERoundingMode newRoundingMode = NumberFormat::ERoundingMode::kRoundCeiling;
    fmtCopy.adoptInstead(new DecimalFormat(*fmt));
    assertFalse("Value before setter", fmtCopy->getRoundingMode() == newRoundingMode);
    fmtCopy->setRoundingMode(newRoundingMode);
    assertEquals("Value after setter", fmtCopy->getRoundingMode(), newRoundingMode);
    fmtCopy->applyPattern(pattern, status);
    assertEquals("Value after applyPattern", fmtCopy->getRoundingMode(), newRoundingMode);
    assertFalse("roundingMode", *fmt == *fmtCopy);

    static const char16_t *const newCurrency = u"EAT";
    fmtCopy.adoptInstead(new DecimalFormat(*fmt));
    assertFalse("Value before setter", fmtCopy->getCurrency() == newCurrency);
    fmtCopy->setCurrency(newCurrency);
    assertEquals("Value after setter", fmtCopy->getCurrency(), newCurrency);
    fmtCopy->applyPattern(pattern, status);
    assertEquals("Value after applyPattern", fmtCopy->getCurrency(), newCurrency);
    assertFalse("currency", *fmt == *fmtCopy);

    static const UCurrencyUsage newCurrencyUsage = UCurrencyUsage::UCURR_USAGE_CASH;
    fmtCopy.adoptInstead(new DecimalFormat(*fmt));
    assertFalse("Value before setter", fmtCopy->getCurrencyUsage() == newCurrencyUsage);
    fmtCopy->setCurrencyUsage(newCurrencyUsage, status);
    assertEquals("Value after setter", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
    fmtCopy->applyPattern(pattern, status);
    assertEquals("Value after applyPattern", fmtCopy->getCurrencyUsage(), newCurrencyUsage);
    assertFalse("currencyUsage", *fmt == *fmtCopy);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestParseNaN() {
    IcuTestErrorCode status(*this, "TestParseNaN");

    DecimalFormat df("0", { "en", status }, status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    Formattable parseResult;
    df.parse(u"NaN", parseResult, status);
    assertEquals("NaN should parse successfully", NAN, parseResult.getDouble());
    assertFalse("Result NaN should be positive", std::signbit(parseResult.getDouble()));
    UnicodeString formatResult;
    df.format(parseResult.getDouble(), formatResult);
    assertEquals("NaN should round-trip", u"NaN", formatResult);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expectPat(DecimalFormat& fmt, const UnicodeString& exp) {
    UnicodeString pat;
    fmt.toPattern(pat);
    if (pat == exp) {
        logln(UnicodeString("Ok   \"") + pat + "\"");
    } else {
        errln(UnicodeString("FAIL \"") + pat + "\", expected \"" + exp + "\"");
    }
}

Project: icu
File: fmtable.cpp

ufmt_open(UErrorCode *status) {
  if( U_FAILURE(*status) ) {
    return NULL;
  }
  UFormattable *fmt = (new Formattable())->toUFormattable();

  if( fmt == NULL ) {
    *status = U_MEMORY_ALLOCATION_ERROR;
  }
  return fmt;
}

Project: icu
File: fmtable.cpp

Formattable::Formattable() {
    init();
}

Project: icu
File: number_decimalquantity.cpp

DecimalQuantity::~DecimalQuantity() {
    if (usingBytes) {
        uprv_free(fBCD.bcdBytes.ptr);
        fBCD.bcdBytes.ptr = nullptr;
        usingBytes = false;
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test13763_FieldPositionIteratorOffset() {
    IcuTestErrorCode status(*this, "Test13763_FieldPositionIteratorOffset");
    FieldPositionIterator fpi;
    UnicodeString result(u"foo\U0001F4FBbar"); // 8 code units
    LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    nf->format(5142.3, result, &fpi, status);

    int32_t expected[] = {
      UNUM_GROUPING_SEPARATOR_FIELD, 9, 10,
      UNUM_INTEGER_FIELD, 8, 13,
      UNUM_DECIMAL_SEPARATOR_FIELD, 13, 14,
      UNUM_FRACTION_FIELD, 14, 15,
    };
    int32_t tupleCount = UPRV_LENGTHOF(expected)/3;
    expectPositions(fpi, expected, tupleCount, result);
}

Project: icu
File: number_decimalquantity.cpp

const char16_t* DecimalQuantity::checkHealth() const {
    if (usingBytes) {
        if (precision == 0) { return u"Zero precision but we are in byte mode"; }
        int32_t capacity = fBCD.bcdBytes.len;
        if (precision > capacity) { return u"Precision exceeds length of byte array"; }
        if (getDigitPos(precision - 1) == 0) { return u"Most significant digit is zero in byte mode"; }
        if (getDigitPos(0) == 0) { return u"Least significant digit is zero in long mode"; }
        for (int i = 0; i < precision; i++) {
            if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in byte array"; }
            if (getDigitPos(i) < 0) { return u"Digit below 0 in byte array"; }
        }
        for (int i = precision; i < capacity; i++) {
            if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in byte array"; }
        }
    } else {
        if (precision == 0 && fBCD.bcdLong != 0) {
            return u"Value in bcdLong even though precision is zero";
        }
        if (precision > 16) { return u"Precision exceeds length of long"; }
        if (precision != 0 && getDigitPos(precision - 1) == 0) {
            return u"Most significant digit is zero in long mode";
        }
        if (precision != 0 && getDigitPos(0) == 0) {
            return u"Least significant digit is zero in long mode";
        }
        for (int i = 0; i < precision; i++) {
            if (getDigitPos(i) >= 10) { return u"Digit exceeding 10 in long"; }
            if (getDigitPos(i) < 0) { return u"Digit below 0 in long (?!)"; }
        }
        for (int i = precision; i < 16; i++) {
            if (getDigitPos(i) != 0) { return u"Nonzero digits outside of range in long"; }
        }
    }

    // No error
    return nullptr;
}

Project: icu
File: fmtable.cpp

void Formattable::dispose()
{
    // Deletes the data value if necessary.
    switch (fType) {
    case kString:
        delete fValue.fString;
        break;
    case kArray:
        delete[] fValue.fArrayAndCount.fArray;
        break;
    case kObject:
        delete fValue.fObject;
        break;
    default:
        break;
    }

    fType = kLong;
    fValue.fInt64 = 0;

    delete fDecimalStr;
    fDecimalStr = NULL;

    delete fDecimalQuantity;
    fDecimalQuantity = NULL;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test13850_EmptyStringCurrency() {
    IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");

    struct TestCase {
        const char16_t* currencyArg;
        UErrorCode expectedError;
    } cases[] = {
        {u"", U_ZERO_ERROR},
        {u"U", U_ILLEGAL_ARGUMENT_ERROR},
        {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
        {nullptr, U_ZERO_ERROR},
        {u"U$D", U_INVARIANT_CONVERSION_ERROR},
        {u"Xxx", U_ZERO_ERROR}
    };
    for (const auto& cas : cases) {
        UnicodeString message(u"with currency arg: ");
        if (cas.currencyArg == nullptr) {
            message += u"nullptr";
        } else {
            message += UnicodeString(cas.currencyArg);
        }
        status.setScope(message);
        LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
        if (status.errIfFailureAndReset()) { return; }
        UnicodeString actual;
        nf->format(1, actual, status);
        status.errIfFailureAndReset();
        assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
        nf->setCurrency(cas.currencyArg, status);
        if (status.expectErrorAndReset(cas.expectedError)) {
            // If an error occurred, do not check formatting.
            continue;
        }
        nf->format(1, actual.remove(), status);
        assertEquals(u"Should unset the currency " + message, u"\u00A41.00", actual);
        status.errIfFailureAndReset();
    }
}

Project: icu
File: number_decimalquantity.cpp

double DecimalQuantity::toDouble() const {
    // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
    // See the comment in the header file explaining the "isApproximate" field.
    U_ASSERT(!isApproximate);

    if (isNaN()) {
        return NAN;
    } else if (isInfinite()) {
        return isNegative() ? -INFINITY : INFINITY;
    }

    // We are processing well-formed input, so we don't need any special options to StringToDoubleConverter.
    StringToDoubleConverter converter(0, 0, 0, "", "");
    UnicodeString numberString = this->toScientificString();
    int32_t count;
    return converter.StringToDouble(
            reinterpret_cast<const uint16_t*>(numberString.getBuffer()),
            numberString.length(),
            &count);
}

Project: icu
File: fmtable.cpp

Formattable::getObject() const {
    return (fType == kObject) ? fValue.fObject : NULL;
}

Project: icu
File: fmtable.cpp

Formattable::setDecimalNumber(StringPiece numberString, UErrorCode &status) {
    if (U_FAILURE(status)) {
        return;
    }
    dispose();

    auto* dq = new DecimalQuantity();
    dq->setToDecNumber(numberString, status);
    adoptDecimalQuantity(dq);

    // Note that we do not hang on to the caller's input string.
    // If we are asked for the string, we will regenerate one from fDecimalQuantity.
}

Project: icu
File: fmtable.cpp

ufmt_getType(const UFormattable *fmt, UErrorCode *status) {
  if(U_FAILURE(*status)) {
    return (UFormattableType)UFMT_COUNT;
  }
  const Formattable *obj = Formattable::fromUFormattable(fmt);
  return (UFormattableType)obj->getType();
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::Test9087(void)
{
    U_STRING_DECL(pattern,"#",1);
    U_STRING_INIT(pattern,"#",1);

    U_STRING_DECL(infstr,"INF",3);
    U_STRING_INIT(infstr,"INF",3);

    U_STRING_DECL(nanstr,"NAN",3);
    U_STRING_INIT(nanstr,"NAN",3);

    UChar outputbuf[50] = {0};
    UErrorCode status = U_ZERO_ERROR;
    UNumberFormat* fmt = unum_open(UNUM_PATTERN_DECIMAL,pattern,1,NULL,NULL,&status);
    if ( U_FAILURE(status) ) {
        dataerrln("FAIL: error in unum_open() - %s", u_errorName(status));
        return;
    }

    unum_setSymbol(fmt,UNUM_INFINITY_SYMBOL,infstr,3,&status);
    unum_setSymbol(fmt,UNUM_NAN_SYMBOL,nanstr,3,&status);
    if ( U_FAILURE(status) ) {
        errln("FAIL: error setting symbols");
    }

    double inf = uprv_getInfinity();

    unum_setAttribute(fmt,UNUM_ROUNDING_MODE,UNUM_ROUND_HALFEVEN);
    unum_setDoubleAttribute(fmt,UNUM_ROUNDING_INCREMENT,0);

    UFieldPosition position = { 0, 0, 0};
    unum_formatDouble(fmt,inf,outputbuf,50,&position,&status);

    if ( u_strcmp(infstr, outputbuf)) {
        errln((UnicodeString)"FAIL: unexpected result for infinity - expected " + infstr + " got " + outputbuf);
    }

    unum_close(fmt);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestParseSignsAndMarks() {
    const SignsAndMarksItem items[] = {
        // locale               lenient numString                                                       value
        { "en",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
        { "en",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
        { "en",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
        { "en",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
        { "en",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
        { "en",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
        { "en",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
        { "en",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },

        { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
        { "en@numbers=arab",    FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
        { "en@numbers=arab",    FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
        { "en@numbers=arab",    TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },

        { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
        { "en@numbers=arabext", FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
        { "en@numbers=arabext", FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
        { "en@numbers=arabext", TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },

        { "he",                 FALSE,  CharsToUnicodeString("12"),                                      12 },
        { "he",                 TRUE,   CharsToUnicodeString("12"),                                      12 },
        { "he",                 FALSE,  CharsToUnicodeString("-23"),                                    -23 },
        { "he",                 TRUE,   CharsToUnicodeString("-23"),                                    -23 },
        { "he",                 TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
        { "he",                 FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
        { "he",                 TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
        { "he",                 TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },

        { "ar",                 FALSE,  CharsToUnicodeString("\\u0663\\u0664"),                          34 },
        { "ar",                 TRUE,   CharsToUnicodeString("\\u0663\\u0664"),                          34 },
        { "ar",                 FALSE,  CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
        { "ar",                 TRUE,   CharsToUnicodeString("-\\u0664\\u0665"),                        -45 },
        { "ar",                 TRUE,   CharsToUnicodeString("- \\u0664\\u0665"),                       -45 },
        { "ar",                 FALSE,  CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
        { "ar",                 TRUE,   CharsToUnicodeString("\\u200F-\\u0664\\u0665"),                 -45 },
        { "ar",                 TRUE,   CharsToUnicodeString("\\u200F- \\u0664\\u0665"),                -45 },

        { "ar_MA",              FALSE,  CharsToUnicodeString("12"),                                      12 },
        { "ar_MA",              TRUE,   CharsToUnicodeString("12"),                                      12 },
        { "ar_MA",              FALSE,  CharsToUnicodeString("-23"),                                    -23 },
        { "ar_MA",              TRUE,   CharsToUnicodeString("-23"),                                    -23 },
        { "ar_MA",              TRUE,   CharsToUnicodeString("- 23"),                                   -23 },
        { "ar_MA",              FALSE,  CharsToUnicodeString("\\u200E-23"),                             -23 },
        { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E-23"),                             -23 },
        { "ar_MA",              TRUE,   CharsToUnicodeString("\\u200E- 23"),                            -23 },

        { "fa",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
        { "fa",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
        { "fa",                 FALSE,  CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
        { "fa",                 TRUE,   CharsToUnicodeString("\\u2212\\u06F6\\u06F7"),                  -67 },
        { "fa",                 TRUE,   CharsToUnicodeString("\\u2212 \\u06F6\\u06F7"),                 -67 },
        { "fa",                 FALSE,  CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
        { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E\\u06F6\\u06F7"),    -67 },
        { "fa",                 TRUE,   CharsToUnicodeString("\\u200E\\u2212\\u200E \\u06F6\\u06F7"),   -67 },

        { "ps",                 FALSE,  CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
        { "ps",                 TRUE,   CharsToUnicodeString("\\u06F5\\u06F6"),                          56 },
        { "ps",                 FALSE,  CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
        { "ps",                 TRUE,   CharsToUnicodeString("-\\u06F6\\u06F7"),                        -67 },
        { "ps",                 TRUE,   CharsToUnicodeString("- \\u06F6\\u06F7"),                       -67 },
        { "ps",                 FALSE,  CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
        { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E\\u06F6\\u06F7"),          -67 },
        { "ps",                 TRUE,   CharsToUnicodeString("\\u200E-\\u200E \\u06F6\\u06F7"),         -67 },
        { "ps",                 FALSE,  CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
        { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E\\u06F6\\u06F7"),                 -67 },
        { "ps",                 TRUE,   CharsToUnicodeString("-\\u200E \\u06F6\\u06F7"),                -67 },
        // terminator
        { NULL,                 0,      UnicodeString(""),                                                0 },
    };

    const SignsAndMarksItem * itemPtr;
    for (itemPtr = items; itemPtr->locale != NULL; itemPtr++ ) {
        UErrorCode status = U_ZERO_ERROR;
        NumberFormat *numfmt = NumberFormat::createInstance(Locale(itemPtr->locale), status);
        if (U_SUCCESS(status)) {
            numfmt->setLenient(itemPtr->lenient);
            Formattable fmtobj;
            ParsePosition ppos;
            numfmt->parse(itemPtr->numString, fmtobj, ppos);
            if (ppos.getIndex() == itemPtr->numString.length()) {
                double parsedValue = fmtobj.getDouble(status);
                if (U_FAILURE(status) || parsedValue != itemPtr->value) {
                    errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives value " + parsedValue);
                }
            } else {
                errln((UnicodeString)"FAIL: locale " + itemPtr->locale + ", lenient " + itemPtr->lenient + ", parse of \"" + itemPtr->numString + "\" gives position " + ppos.getIndex());
            }
        } else {
            dataerrln("FAIL: NumberFormat::createInstance for locale % gives error %s", itemPtr->locale, u_errorName(status));
        }
        delete numfmt;
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestZeroScientific10547() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormat fmt("0.00E0", status);
    if (!assertSuccess("Format creation", status)) {
        return;
    }
    UnicodeString out;
    fmt.format(-0.0, out);
    assertEquals("format", "-0.00E0", out, true);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test13737_ParseScientificStrict() {
    IcuTestErrorCode status(*this, "Test13737_ParseScientificStrict");
    LocalPointer<NumberFormat> df(NumberFormat::createScientificInstance("en", status), status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) {return;}
    df->setLenient(FALSE);
    // Parse Test
    expect(*df, u"1.2", 1.2);
}

Project: icu
File: fmtable.cpp

ufmt_getArrayItemByIndex(UFormattable* fmt, int32_t n, UErrorCode *status) {
  Formattable *obj = Formattable::fromUFormattable(fmt);
  int32_t count;
  (void)obj->getArray(count, *status);
  if(U_FAILURE(*status)) {
    return NULL;
  } else if(n<0 || n>=count) {
    setError(*status, U_INDEX_OUTOFBOUNDS_ERROR);
    return NULL;
  } else {
    return (*obj)[n].toUFormattable(); // returns non-const Formattable
  }
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::shiftRight(int32_t numDigits) {
    if (usingBytes) {
        int i = 0;
        for (; i < precision - numDigits; i++) {
            fBCD.bcdBytes.ptr[i] = fBCD.bcdBytes.ptr[i + numDigits];
        }
        for (; i < precision; i++) {
            fBCD.bcdBytes.ptr[i] = 0;
        }
    } else {
        fBCD.bcdLong >>= (numDigits * 4);
    }
    scale += numDigits;
    precision -= numDigits;
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::setFractionLength(int32_t minFrac, int32_t maxFrac) {
    // Validation should happen outside of DecimalQuantity, e.g., in the Precision class.
    U_ASSERT(minFrac >= 0);
    U_ASSERT(maxFrac >= minFrac);

    // Save values into internal state
    // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE
    rReqPos = -minFrac;
    rOptPos = -maxFrac;
}

Project: icu
File: number_decimalquantity.cpp

DecimalQuantity::DecimalQuantity(const DecimalQuantity &other) {
    *this = other;
}

Project: icu
File: fmtable.cpp

Formattable::getDouble(UErrorCode& status) const
{
    if (U_FAILURE(status)) {
        return 0;
    }
        
    switch (fType) {
    case Formattable::kLong: 
    case Formattable::kInt64: // loses precision
        return (double)fValue.fInt64;
    case Formattable::kDouble:
        return fValue.fDouble;
    case Formattable::kObject:
        if (fValue.fObject == NULL) {
            status = U_MEMORY_ALLOCATION_ERROR;
            return 0;
        }
        // TODO Later replace this with instanceof call
        if (instanceOfMeasure(fValue.fObject)) {
            return ((const Measure*) fValue.fObject)->
                getNumber().getDouble(status);
        }
        U_FALLTHROUGH;
    default:
        status = U_INVALID_FORMAT_ERROR;
        return 0;
    }
}

Project: icu
File: fmtable.cpp

static inline UBool instanceOfMeasure(const UObject* a) {
    return dynamic_cast<const Measure*>(a) != NULL;
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::ensureCapacity(int32_t capacity) {
    if (capacity == 0) { return; }
    int32_t oldCapacity = usingBytes ? fBCD.bcdBytes.len : 0;
    if (!usingBytes) {
        // TODO: There is nothing being done to check for memory allocation failures.
        // TODO: Consider indexing by nybbles instead of bytes in C++, so that we can
        // make these arrays half the size.
        fBCD.bcdBytes.ptr = static_cast<int8_t*>(uprv_malloc(capacity * sizeof(int8_t)));
        fBCD.bcdBytes.len = capacity;
        // Initialize the byte array to zeros (this is done automatically in Java)
        uprv_memset(fBCD.bcdBytes.ptr, 0, capacity * sizeof(int8_t));
    } else if (oldCapacity < capacity) {
        auto bcd1 = static_cast<int8_t*>(uprv_malloc(capacity * 2 * sizeof(int8_t)));
        uprv_memcpy(bcd1, fBCD.bcdBytes.ptr, oldCapacity * sizeof(int8_t));
        // Initialize the rest of the byte array to zeros (this is done automatically in Java)
        uprv_memset(bcd1 + oldCapacity, 0, (capacity - oldCapacity) * sizeof(int8_t));
        uprv_free(fBCD.bcdBytes.ptr);
        fBCD.bcdBytes.ptr = bcd1;
        fBCD.bcdBytes.len = capacity * 2;
    }
    usingBytes = true;
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestCoverage(void){
    StubNumberFormat stub;
    UnicodeString agent("agent");
    FieldPosition pos;
    int64_t num = 4;
    if (stub.format(num, agent, pos) != UnicodeString("agent3")){
        errln("NumberFormat::format(int64, UnicodString&, FieldPosition&) should delegate to (int32, ,)");
    };
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expect2(NumberFormat* fmt, const Formattable& n,
                               const UnicodeString& exp,
                               UErrorCode status) {
    if (fmt == NULL || U_FAILURE(status)) {
        dataerrln("FAIL: NumberFormat constructor");
    } else {
        expect2(*fmt, n, exp);
    }
    delete fmt;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestParseNegativeWithFaLocale() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormat *test = (DecimalFormat *) NumberFormat::createInstance("fa", status);
    CHECK_DATA(status, "NumberFormat::createInstance")
    test->setLenient(TRUE);
    Formattable af;
    ParsePosition ppos;
    UnicodeString value("\\u200e-0,5");
    value = value.unescape();
    test->parse(value, af, ppos);
    if (ppos.getIndex() == 0) {
        errln("Expected -0,5 to parse for Farsi.");
    }
    delete test;
}

Project: icu
File: number_decimalquantity.cpp

DecimalQuantity& DecimalQuantity::operator=(DecimalQuantity&& src) U_NOEXCEPT {
    if (this == &src) {
        return *this;
    }
    moveBcdFrom(src);
    copyFieldsFrom(src);
    return *this;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11376_getAndSetPositivePrefix() {
    {
        const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
        UErrorCode status = U_ZERO_ERROR;
        LocalPointer<NumberFormat> fmt(
                NumberFormat::createCurrencyInstance("en", status));
        if (!assertSuccess("", status)) {
            return;
        }
        DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
        dfmt->setCurrency(USD);
        UnicodeString result;

        // This line should be a no-op. I am setting the positive prefix
        // to be the same thing it was before.
        dfmt->setPositivePrefix(dfmt->getPositivePrefix(result));

        UnicodeString appendTo;
        assertEquals("", "$3.78", dfmt->format(3.78, appendTo, status));
        assertSuccess("", status);
    }
    {
        const UChar USD[] = {0x55, 0x53, 0x44, 0x0};
        UErrorCode status = U_ZERO_ERROR;
        LocalPointer<NumberFormat> fmt(
                NumberFormat::createInstance("en", UNUM_CURRENCY_PLURAL, status));
        if (!assertSuccess("", status)) {
            return;
        }
        DecimalFormat *dfmt = (DecimalFormat *) fmt.getAlias();
        UnicodeString result;
        assertEquals("", u" (unknown currency)", dfmt->getPositiveSuffix(result));
        dfmt->setCurrency(USD);

        // getPositiveSuffix() always returns the suffix for the
        // "other" plural category
        assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
        UnicodeString appendTo;
        assertEquals("", "3.78 US dollars", dfmt->format(3.78, appendTo, status));
        assertEquals("", " US dollars", dfmt->getPositiveSuffix(result));
        dfmt->setPositiveSuffix("booya");
        appendTo.remove();
        assertEquals("", "3.78booya", dfmt->format(3.78, appendTo, status));
        assertEquals("", "booya", dfmt->getPositiveSuffix(result));
    }
}

Project: icu
File: number_decimalquantity.cpp

DecimalQuantity &DecimalQuantity::setToLong(int64_t n) {
    setBcdToZero();
    flags = 0;
    if (n < 0 && n > INT64_MIN) {
        flags |= NEGATIVE_FLAG;
        n = -n;
    }
    if (n != 0) {
        _setToLong(n);
        compact();
    }
    return *this;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11913_BigDecimal() {
    UErrorCode status = U_ZERO_ERROR;
    LocalPointer<NumberFormat> df(NumberFormat::createInstance(Locale::getEnglish(), status), status);
    if (!assertSuccess("", status)) return;
    UnicodeString result;
    df->format(StringPiece("1.23456789E400"), result, nullptr, status);
    assertSuccess("", status);
    assertEquals("Should format more than 309 digits", u"12,345,678", UnicodeString(result, 0, 10));
    assertEquals("Should format more than 309 digits", 534, result.length());
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestFractionalDigitsForCurrency() {
    UErrorCode status = U_ZERO_ERROR;
    LocalPointer<NumberFormat> fmt(NumberFormat::createCurrencyInstance("en", status));
    if (U_FAILURE(status)) {
        dataerrln("Error creating NumberFormat - %s", u_errorName(status));
        return;
    }
    UChar JPY[] = {0x4A, 0x50, 0x59, 0x0};
    fmt->setCurrency(JPY, status);
    if (!assertSuccess("", status)) {
        return;
    }
    assertEquals("", 0, fmt->getMaximumFractionDigits());
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestExponent(void) {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols US(Locale::getUS(), status);
    CHECK(status, "DecimalFormatSymbols constructor");
    DecimalFormat fmt1(UnicodeString("0.###E0"), US, status);
    CHECK(status, "DecimalFormat(0.###E0)");
    DecimalFormat fmt2(UnicodeString("0.###E+0"), US, status);
    CHECK(status, "DecimalFormat(0.###E+0)");
    int32_t n = 1234;
    expect2(fmt1, n, "1.234E3");
    expect2(fmt2, n, "1.234E+3");
    expect(fmt1, "1.234E+3", n); // Either format should parse "E+3"
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11897_LocalizedPatternSeparator() {
    IcuTestErrorCode status(*this, "Test11897_LocalizedPatternSeparator");

    // In a locale with a different <list> symbol, like arabic,
    // kPatternSeparatorSymbol should still be ';'
    {
        DecimalFormatSymbols dfs("ar", status);
        assertEquals("pattern separator symbol should be ;",
                u";",
                dfs.getSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol));
    }

    // However, the custom symbol should be used in localized notation
    // when set manually via API
    {
        DecimalFormatSymbols dfs("en", status);
        dfs.setSymbol(DecimalFormatSymbols::kPatternSeparatorSymbol, u"!", FALSE);
        DecimalFormat df(u"0", dfs, status);
        if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
        df.applyPattern("a0;b0", status); // should not throw
        UnicodeString result;
        assertEquals("should apply the normal pattern",
                df.getNegativePrefix(result.remove()),
                "b");
        df.applyLocalizedPattern(u"c0!d0", status); // should not throw
        assertEquals("should apply the localized pattern",
                df.getNegativePrefix(result.remove()),
                "d");
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test20073_StrictPercentParseErrorIndex() {
    IcuTestErrorCode status(*this, "Test20073_StrictPercentParseErrorIndex");
    ParsePosition parsePosition(0);
    DecimalFormat df(u"0%", {"en-us", status}, status);
    if (U_FAILURE(status)) {
        dataerrln("Unable to create DecimalFormat instance.");
        return;
    }
    df.setLenient(FALSE);
    Formattable result;
    df.parse(u"%2%", result, parsePosition);
    assertEquals("", 0, parsePosition.getIndex());
    assertEquals("", 0, parsePosition.getErrorIndex());
}

Project: icu
File: number_decimalquantity.cpp

bool DecimalQuantity::isInfinite() const {
    return (flags & INFINITY_FLAG) != 0;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11475_signRecognition() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols sym("en", status);
    UnicodeString result;
    {
        DecimalFormat fmt("+0.00", sym, status);
        if (!assertSuccess("", status)) {
            return;
        }
        NumberFormatTest_Attributes attributes[] = {
                {UNUM_SIGN_FIELD, 0, 1},
                {UNUM_INTEGER_FIELD, 1, 2},
                {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
                {UNUM_FRACTION_FIELD, 3, 5},
                {0, -1, 0}};
        UnicodeString result;
        FieldPositionIterator iter;
        fmt.format(2.3, result, &iter, status);
        assertEquals("", "+2.30", result);
        verifyFieldPositionIterator(attributes, iter);
    }
    {
        DecimalFormat fmt("++0.00+;-(#)--", sym, status);
        if (!assertSuccess("", status)) {
            return;
        }
        {
            NumberFormatTest_Attributes attributes[] = {
                    {UNUM_SIGN_FIELD, 0, 2},
                    {UNUM_INTEGER_FIELD, 2, 3},
                    {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
                    {UNUM_FRACTION_FIELD, 4, 6},
                    {UNUM_SIGN_FIELD, 6, 7},
                    {0, -1, 0}};
            UnicodeString result;
            FieldPositionIterator iter;
            fmt.format(2.3, result, &iter, status);
            assertEquals("", "++2.30+", result);
            verifyFieldPositionIterator(attributes, iter);
        }
        {
            NumberFormatTest_Attributes attributes[] = {
                    {UNUM_SIGN_FIELD, 0, 1},
                    {UNUM_INTEGER_FIELD, 2, 3},
                    {UNUM_DECIMAL_SEPARATOR_FIELD, 3, 4},
                    {UNUM_FRACTION_FIELD, 4, 6},
                    {UNUM_SIGN_FIELD, 7, 9},
                    {0, -1, 0}};
            UnicodeString result;
            FieldPositionIterator iter;
            fmt.format(-2.3, result, &iter, status);
            assertEquals("", "-(2.30)--", result);
            verifyFieldPositionIterator(attributes, iter);
        }
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCurrencyObject() {
    UErrorCode ec = U_ZERO_ERROR;
    NumberFormat* fmt =
        NumberFormat::createCurrencyInstance(Locale::getUS(), ec);

    if (U_FAILURE(ec)) {
        dataerrln("FAIL: getCurrencyInstance(US) - %s", u_errorName(ec));
        delete fmt;
        return;
    }

    Locale null("", "", "");

    expectCurrency(*fmt, null, 1234.56, "$1,234.56");

    expectCurrency(*fmt, Locale::getFrance(),
                   1234.56, CharsToUnicodeString("\\u20AC1,234.56")); // Euro

    expectCurrency(*fmt, Locale::getJapan(),
                   1234.56, CharsToUnicodeString("\\u00A51,235")); // Yen

    expectCurrency(*fmt, Locale("fr", "CH", ""),
                   1234.56, "CHF 1,234.56"); // no more 0.05 rounding here, see cldrbug 5548

    expectCurrency(*fmt, Locale::getUS(),
                   1234.56, "$1,234.56");

    delete fmt;
    fmt = NumberFormat::createCurrencyInstance(Locale::getFrance(), ec);

    if (U_FAILURE(ec)) {
        errln("FAIL: getCurrencyInstance(FRANCE)");
        delete fmt;
        return;
    }

    expectCurrency(*fmt, null, 1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC"));

    expectCurrency(*fmt, Locale::getJapan(),
                   1234.56, CharsToUnicodeString("1\\u202F235 JPY")); // Yen

    expectCurrency(*fmt, Locale("fr", "CH", ""),
                   1234.56, CharsToUnicodeString("1\\u202F234,56 CHF")); // no more 0.05 rounding here, see cldrbug 5548

    expectCurrency(*fmt, Locale::getUS(),
                   1234.56, CharsToUnicodeString("1\\u202F234,56 $US"));

    expectCurrency(*fmt, Locale::getFrance(),
                   1234.56, CharsToUnicodeString("1\\u202F234,56 \\u20AC")); // Euro

    delete fmt;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCurrencyFractionDigits() {
    UErrorCode status = U_ZERO_ERROR;
    UnicodeString text1, text2;
    double value = 99.12345;

    // Create currenct instance
    NumberFormat* fmt = NumberFormat::createCurrencyInstance("ja_JP", status);
    if (U_FAILURE(status) || fmt == NULL) {
        dataerrln("Unable to create NumberFormat");
    } else {
        fmt->format(value, text1);

        // Reset the same currency and format the test value again
        fmt->setCurrency(fmt->getCurrency(), status);
        ASSERT_SUCCESS(status);
        fmt->format(value, text2);

        if (text1 != text2) {
            errln((UnicodeString)"NumberFormat::format() should return the same result - text1="
                + text1 + " text2=" + text2);
        }
    }
    delete fmt;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11868() {
    double posAmt = 34.567;
    double negAmt = -9876.543;

    Locale selectedLocale("en_US");
    UErrorCode status = U_ZERO_ERROR;

    UnicodeString result;
    FieldPosition fpCurr(UNUM_CURRENCY_FIELD);
    LocalPointer<NumberFormat> fmt(
            NumberFormat::createInstance(
                    selectedLocale, UNUM_CURRENCY_PLURAL, status));
    if (!assertSuccess("Format creation", status)) {
        return;
    }
    fmt->format(posAmt, result, fpCurr, status);
    assertEquals("", "34.57 US dollars", result);
    assertEquals("begin index", 6, fpCurr.getBeginIndex());
    assertEquals("end index", 16, fpCurr.getEndIndex());

    // Test field position iterator
    {
        NumberFormatTest_Attributes attributes[] = {
                {UNUM_INTEGER_FIELD, 0, 2},
                {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
                {UNUM_FRACTION_FIELD, 3, 5},
                {UNUM_CURRENCY_FIELD, 6, 16},
                {0, -1, 0}};
        UnicodeString result;
        FieldPositionIterator iter;
        fmt->format(posAmt, result, &iter, status);
        assertEquals("", "34.57 US dollars", result);
        verifyFieldPositionIterator(attributes, iter);
    }

    result.remove();
    fmt->format(negAmt, result, fpCurr, status);
    assertEquals("", "-9,876.54 US dollars", result);
    assertEquals("begin index", 10, fpCurr.getBeginIndex());
    assertEquals("end index", 20, fpCurr.getEndIndex());

    // Test field position iterator
    {
        NumberFormatTest_Attributes attributes[] = {
                {UNUM_SIGN_FIELD, 0, 1},
                {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
                {UNUM_INTEGER_FIELD, 1, 6},
                {UNUM_DECIMAL_SEPARATOR_FIELD, 6, 7},
                {UNUM_FRACTION_FIELD, 7, 9},
                {UNUM_CURRENCY_FIELD, 10, 20},
                {0, -1, 0}};
        UnicodeString result;
        FieldPositionIterator iter;
        fmt->format(negAmt, result, &iter, status);
        assertEquals("", "-9,876.54 US dollars", result);
        verifyFieldPositionIterator(attributes, iter);
    }
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::roundToNickel(int32_t magnitude, RoundingMode roundingMode, UErrorCode& status) {
    roundToMagnitude(magnitude, roundingMode, true, status);
}

Project: icu
File: number_decimalquantity.cpp

int32_t DecimalQuantity::getMagnitude() const {
    U_ASSERT(precision != 0);
    return scale + precision - 1;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestScientific(void) {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols US(Locale::getUS(), status);
    CHECK(status, "DecimalFormatSymbols constructor");

    // Test pattern round-trip
    const char* PAT[] = { "#E0", "0.####E0", "00.000E00", "##0.####E000",
                          "0.###E0;[0.###E0]" };
    int32_t PAT_length = UPRV_LENGTHOF(PAT);
    int32_t DIGITS[] = {
        // min int, max int, min frac, max frac
        1, 1, 0, 0, // "#E0"
        1, 1, 0, 4, // "0.####E0"
        2, 2, 3, 3, // "00.000E00"
        1, 3, 0, 4, // "##0.####E000"
        1, 1, 0, 3, // "0.###E0;[0.###E0]"
    };
    for (int32_t i=0; i<PAT_length; ++i) {
        UnicodeString pat(PAT[i]);
        DecimalFormat df(pat, US, status);
        CHECK(status, "DecimalFormat constructor");
        UnicodeString pat2;
        df.toPattern(pat2);
        if (pat == pat2) {
            logln(UnicodeString("Ok   Pattern rt \"") +
                  pat + "\" -> \"" +
                  pat2 + "\"");
        } else {
            errln(UnicodeString("FAIL Pattern rt \"") +
                  pat + "\" -> \"" +
                  pat2 + "\"");
        }
        // Make sure digit counts match what we expect
        if (df.getMinimumIntegerDigits() != DIGITS[4*i] ||
            df.getMaximumIntegerDigits() != DIGITS[4*i+1] ||
            df.getMinimumFractionDigits() != DIGITS[4*i+2] ||
            df.getMaximumFractionDigits() != DIGITS[4*i+3]) {
            errln(UnicodeString("FAIL \"" + pat +
                                "\" min/max int; min/max frac = ") +
                  df.getMinimumIntegerDigits() + "/" +
                  df.getMaximumIntegerDigits() + ";" +
                  df.getMinimumFractionDigits() + "/" +
                  df.getMaximumFractionDigits() + ", expect " +
                  DIGITS[4*i] + "/" +
                  DIGITS[4*i+1] + ";" +
                  DIGITS[4*i+2] + "/" +
                  DIGITS[4*i+3]);
        }
    }


    // Test the constructor for default locale. We have to
    // manually set the default locale, as there is no
    // guarantee that the default locale has the same
    // scientific format.
    Locale def = Locale::getDefault();
    Locale::setDefault(Locale::getUS(), status);
    expect2(NumberFormat::createScientificInstance(status),
           12345.678901,
           "1.2345678901E4", status);
    Locale::setDefault(def, status);

    expect2(new DecimalFormat("#E0", US, status),
           12345.0,
           "1.2345E4", status);
    expect(new DecimalFormat("0E0", US, status),
           12345.0,
           "1E4", status);
    expect2(NumberFormat::createScientificInstance(Locale::getUS(), status),
           12345.678901,
           "1.2345678901E4", status);
    expect(new DecimalFormat("##0.###E0", US, status),
           12345.0,
           "12.34E3", status);
    expect(new DecimalFormat("##0.###E0", US, status),
           12345.00001,
           "12.35E3", status);
    expect2(new DecimalFormat("##0.####E0", US, status),
           (int32_t) 12345,
           "12.345E3", status);
    expect2(NumberFormat::createScientificInstance(Locale::getFrance(), status),
           12345.678901,
           "1,2345678901E4", status);
    expect(new DecimalFormat("##0.####E0", US, status),
           789.12345e-9,
           "789.12E-9", status);
    expect2(new DecimalFormat("##0.####E0", US, status),
           780.e-9,
           "780E-9", status);
    expect(new DecimalFormat(".###E0", US, status),
           45678.0,
           ".457E5", status);
    expect2(new DecimalFormat(".###E0", US, status),
           (int32_t) 0,
           ".0E0", status);
    /*
    expect(new DecimalFormat[] { new DecimalFormat("#E0", US),
                                 new DecimalFormat("##E0", US),
                                 new DecimalFormat("####E0", US),
                                 new DecimalFormat("0E0", US),
                                 new DecimalFormat("00E0", US),
                                 new DecimalFormat("000E0", US),
                               },
           new Long(45678000),
           new String[] { "4.5678E7",
                          "45.678E6",
                          "4567.8E4",
                          "5E7",
                          "46E6",
                          "457E5",
                        }
           );
    !
    ! Unroll this test into individual tests below...
    !
    */
    expect2(new DecimalFormat("#E0", US, status),
           (int32_t) 45678000, "4.5678E7", status);
    expect2(new DecimalFormat("##E0", US, status),
           (int32_t) 45678000, "45.678E6", status);
    expect2(new DecimalFormat("####E0", US, status),
           (int32_t) 45678000, "4567.8E4", status);
    expect(new DecimalFormat("0E0", US, status),
           (int32_t) 45678000, "5E7", status);
    expect(new DecimalFormat("00E0", US, status),
           (int32_t) 45678000, "46E6", status);
    expect(new DecimalFormat("000E0", US, status),
           (int32_t) 45678000, "457E5", status);
    /*
    expect(new DecimalFormat("###E0", US, status),
           new Object[] { new Double(0.0000123), "12.3E-6",
                          new Double(0.000123), "123E-6",
                          new Double(0.00123), "1.23E-3",
                          new Double(0.0123), "12.3E-3",
                          new Double(0.123), "123E-3",
                          new Double(1.23), "1.23E0",
                          new Double(12.3), "12.3E0",
                          new Double(123), "123E0",
                          new Double(1230), "1.23E3",
                         });
    !
    ! Unroll this test into individual tests below...
    !
    */
    expect2(new DecimalFormat("###E0", US, status),
           0.0000123, "12.3E-6", status);
    expect2(new DecimalFormat("###E0", US, status),
           0.000123, "123E-6", status);
    expect2(new DecimalFormat("###E0", US, status),
           0.00123, "1.23E-3", status);
    expect2(new DecimalFormat("###E0", US, status),
           0.0123, "12.3E-3", status);
    expect2(new DecimalFormat("###E0", US, status),
           0.123, "123E-3", status);
    expect2(new DecimalFormat("###E0", US, status),
           1.23, "1.23E0", status);
    expect2(new DecimalFormat("###E0", US, status),
           12.3, "12.3E0", status);
    expect2(new DecimalFormat("###E0", US, status),
           123.0, "123E0", status);
    expect2(new DecimalFormat("###E0", US, status),
           1230.0, "1.23E3", status);
    /*
    expect(new DecimalFormat("0.#E+00", US, status),
           new Object[] { new Double(0.00012), "1.2E-04",
                          new Long(12000),     "1.2E+04",
                         });
    !
    ! Unroll this test into individual tests below...
    !
    */
    expect2(new DecimalFormat("0.#E+00", US, status),
           0.00012, "1.2E-04", status);
    expect2(new DecimalFormat("0.#E+00", US, status),
           (int32_t) 12000, "1.2E+04", status);
}

Project: icu
File: number_decimalquantity.cpp

UnicodeString DecimalQuantity::toPlainString() const {
    U_ASSERT(!isApproximate);
    UnicodeString sb;
    if (isNegative()) {
        sb.append(u'-');
    }
    if (precision == 0 || getMagnitude() < 0) {
        sb.append(u'0');
    }
    for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
        if (m == -1) { sb.append(u'.'); }
        sb.append(getDigit(m) + u'0');
    }
    return sb;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestFormatAttributes() {
  Locale locale("en_US");
  UErrorCode status = U_ZERO_ERROR;
  DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_CURRENCY, status);
    if (failure(status, "NumberFormat::createInstance", TRUE)) return;
  double val = 12345.67;

  {
    int32_t expected[] = {
      UNUM_CURRENCY_FIELD, 0, 1,
      UNUM_GROUPING_SEPARATOR_FIELD, 3, 4,
      UNUM_INTEGER_FIELD, 1, 7,
      UNUM_DECIMAL_SEPARATOR_FIELD, 7, 8,
      UNUM_FRACTION_FIELD, 8, 10,
    };
    int32_t tupleCount = UPRV_LENGTHOF(expected)/3;

    FieldPositionIterator posIter;
    UnicodeString result;
    decFmt->format(val, result, &posIter, status);
    expectPositions(posIter, expected, tupleCount, result);
  }
  {
    FieldPosition fp(UNUM_INTEGER_FIELD);
    UnicodeString result;
    decFmt->format(val, result, fp);
    expectPosition(fp, UNUM_INTEGER_FIELD, 1, 7, result);
  }
  {
    FieldPosition fp(UNUM_FRACTION_FIELD);
    UnicodeString result;
    decFmt->format(val, result, fp);
    expectPosition(fp, UNUM_FRACTION_FIELD, 8, 10, result);
  }
  delete decFmt;

  decFmt = (DecimalFormat *) NumberFormat::createInstance(locale, UNUM_SCIENTIFIC, status);
  val = -0.0000123;
  {
    int32_t expected[] = {
      UNUM_SIGN_FIELD, 0, 1,
      UNUM_INTEGER_FIELD, 1, 2,
      UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3,
      UNUM_FRACTION_FIELD, 3, 5,
      UNUM_EXPONENT_SYMBOL_FIELD, 5, 6,
      UNUM_EXPONENT_SIGN_FIELD, 6, 7,
      UNUM_EXPONENT_FIELD, 7, 8
    };
    int32_t tupleCount = UPRV_LENGTHOF(expected)/3;

    FieldPositionIterator posIter;
    UnicodeString result;
    decFmt->format(val, result, &posIter, status);
    expectPositions(posIter, expected, tupleCount, result);
  }
  {
    FieldPosition fp(UNUM_INTEGER_FIELD);
    UnicodeString result;
    decFmt->format(val, result, fp);
    expectPosition(fp, UNUM_INTEGER_FIELD, 1, 2, result);
  }
  {
    FieldPosition fp(UNUM_FRACTION_FIELD);
    UnicodeString result;
    decFmt->format(val, result, fp);
    expectPosition(fp, UNUM_FRACTION_FIELD, 3, 5, result);
  }
  delete decFmt;

  fflush(stderr);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestFieldPositionIterator() {
  // bug 7372
  UErrorCode status = U_ZERO_ERROR;
  FieldPositionIterator iter1;
  FieldPositionIterator iter2;
  FieldPosition pos;

  DecimalFormat *decFmt = (DecimalFormat *) NumberFormat::createInstance(status);
  if (failure(status, "NumberFormat::createInstance", TRUE)) return;

  double num = 1234.56;
  UnicodeString str1;
  UnicodeString str2;

  assertTrue((UnicodeString)"self==", iter1 == iter1);
  assertTrue((UnicodeString)"iter1==iter2", iter1 == iter2);

  decFmt->format(num, str1, &iter1, status);
  assertTrue((UnicodeString)"iter1 != iter2", iter1 != iter2);
  decFmt->format(num, str2, &iter2, status);
  assertTrue((UnicodeString)"iter1 == iter2 (2)", iter1 == iter2);
  iter1.next(pos);
  assertTrue((UnicodeString)"iter1 != iter2 (2)", iter1 != iter2);
  iter2.next(pos);
  assertTrue((UnicodeString)"iter1 == iter2 (3)", iter1 == iter2);

  // should format ok with no iterator
  str2.remove();
  decFmt->format(num, str2, NULL, status);
  assertEquals("null fpiter", str1, str2);

  delete decFmt;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test11318_DoubleConversion() {
    IcuTestErrorCode status(*this, "Test11318_DoubleConversion");
    LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
    if (U_FAILURE(status)) {
      dataerrln("%s %d Error in NumberFormat instance creation",  __FILE__, __LINE__);
      return;
    }
    nf->setMaximumFractionDigits(40);
    nf->setMaximumIntegerDigits(40);
    UnicodeString appendTo;
    nf->format(999999999999999.9, appendTo);
    assertEquals("Should render all digits", u"999,999,999,999,999.9", appendTo);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test20037_ScientificIntegerOverflow() {
    IcuTestErrorCode status(*this, "Test20037_ScientificIntegerOverflow");

    LocalPointer<NumberFormat> nf(NumberFormat::createInstance(status));
    if (U_FAILURE(status)) {
        dataerrln("Unable to create NumberFormat instance.");
        return;
    }
    Formattable result;

    // Test overflow of exponent
    nf->parse(u"1E-2147483648", result, status);
    StringPiece sp = result.getDecimalNumber(status);
    assertEquals(u"Should snap to zero",
                 u"0",
                 {sp.data(), sp.length(), US_INV});

    // Test edge case overflow of exponent
    result = Formattable();
    nf->parse(u"1E-2147483647E-1", result, status);
    sp = result.getDecimalNumber(status);
    assertEquals(u"Should not overflow and should parse only the first exponent",
                 u"1E-2147483647",
                 {sp.data(), sp.length(), US_INV});

    // Test edge case overflow of exponent
    result = Formattable();
    nf->parse(u".0003e-2147483644", result, status);
    sp = result.getDecimalNumber(status);
    assertEquals(u"Should not overflow",
                 u"3E-2147483648",
                 {sp.data(), sp.length(), US_INV});
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCurrencyNames(void) {
    // Do a basic check of getName()
    // USD { "US$", "US Dollar"            } // 04/04/1792-
    UErrorCode ec = U_ZERO_ERROR;
    static const UChar USD[] = {0x55, 0x53, 0x44, 0}; /*USD*/
    static const UChar USX[] = {0x55, 0x53, 0x58, 0}; /*USX*/
    static const UChar CAD[] = {0x43, 0x41, 0x44, 0}; /*CAD*/
    static const UChar ITL[] = {0x49, 0x54, 0x4C, 0}; /*ITL*/
    UBool isChoiceFormat;
    int32_t len;
    const UBool possibleDataError = TRUE;
    // Warning: HARD-CODED LOCALE DATA in this test.  If it fails, CHECK
    // THE LOCALE DATA before diving into the code.
    assertEquals("USD.getName(SYMBOL_NAME, en)",
                 UnicodeString("$"),
                 UnicodeString(ucurr_getName(USD, "en",
                                             UCURR_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USD.getName(NARROW_SYMBOL_NAME, en)",
                 UnicodeString("$"),
                 UnicodeString(ucurr_getName(USD, "en",
                                             UCURR_NARROW_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USD.getName(LONG_NAME, en)",
                 UnicodeString("US Dollar"),
                 UnicodeString(ucurr_getName(USD, "en",
                                             UCURR_LONG_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("CAD.getName(SYMBOL_NAME, en)",
                 UnicodeString("CA$"),
                 UnicodeString(ucurr_getName(CAD, "en",
                                             UCURR_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("CAD.getName(NARROW_SYMBOL_NAME, en)",
                 UnicodeString("$"),
                 UnicodeString(ucurr_getName(CAD, "en",
                                             UCURR_NARROW_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("CAD.getName(SYMBOL_NAME, en_CA)",
                 UnicodeString("$"),
                 UnicodeString(ucurr_getName(CAD, "en_CA",
                                             UCURR_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USD.getName(SYMBOL_NAME, en_CA)",
                 UnicodeString("US$"),
                 UnicodeString(ucurr_getName(USD, "en_CA",
                                             UCURR_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USD.getName(NARROW_SYMBOL_NAME, en_CA)",
                 UnicodeString("$"),
                 UnicodeString(ucurr_getName(USD, "en_CA",
                                             UCURR_NARROW_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USD.getName(SYMBOL_NAME) in en_NZ",
                 UnicodeString("US$"),
                 UnicodeString(ucurr_getName(USD, "en_NZ",
                                             UCURR_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("CAD.getName(SYMBOL_NAME)",
                 UnicodeString("CA$"),
                 UnicodeString(ucurr_getName(CAD, "en_NZ",
                                             UCURR_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USX.getName(SYMBOL_NAME)",
                 UnicodeString("USX"),
                 UnicodeString(ucurr_getName(USX, "en_US",
                                             UCURR_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USX.getName(NARROW_SYMBOL_NAME)",
                 UnicodeString("USX"),
                 UnicodeString(ucurr_getName(USX, "en_US",
                                             UCURR_NARROW_SYMBOL_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertEquals("USX.getName(LONG_NAME)",
                 UnicodeString("USX"),
                 UnicodeString(ucurr_getName(USX, "en_US",
                                             UCURR_LONG_NAME,
                                             &isChoiceFormat, &len, &ec)),
                                             possibleDataError);
    assertSuccess("ucurr_getName", ec);

    ec = U_ZERO_ERROR;

    // Test that a default or fallback warning is being returned. JB 4239.
    ucurr_getName(CAD, "es_ES", UCURR_LONG_NAME, &isChoiceFormat,
                            &len, &ec);
    assertTrue("ucurr_getName (es_ES fallback)",
                    U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);

    ucurr_getName(CAD, "zh_TW", UCURR_LONG_NAME, &isChoiceFormat,
                            &len, &ec);
    assertTrue("ucurr_getName (zh_TW fallback)",
                    U_USING_FALLBACK_WARNING == ec, TRUE, possibleDataError);

    ucurr_getName(CAD, "en_US", UCURR_LONG_NAME, &isChoiceFormat,
                            &len, &ec);
    assertTrue("ucurr_getName (en_US default)",
                    U_USING_DEFAULT_WARNING == ec || U_USING_FALLBACK_WARNING == ec, TRUE);

    ucurr_getName(CAD, "ti", UCURR_LONG_NAME, &isChoiceFormat,
                            &len, &ec);
    assertTrue("ucurr_getName (ti default)",
                    U_USING_DEFAULT_WARNING == ec, TRUE);

    // Test that a default warning is being returned when falling back to root. JB 4536.
    ucurr_getName(ITL, "cy", UCURR_LONG_NAME, &isChoiceFormat,
                            &len, &ec);
    assertTrue("ucurr_getName (cy default to root)",
                    U_USING_DEFAULT_WARNING == ec, TRUE);

    // TODO add more tests later
}

Project: icu
File: fmtable.cpp

Formattable::adoptObject(UObject* objectToAdopt) {
    dispose();
    fType = kObject;
    fValue.fObject = objectToAdopt;
}

Project: icu
File: fmtable.cpp

ufmt_getDecNumChars(UFormattable *fmt, int32_t *len, UErrorCode *status) {
  if(U_FAILURE(*status)) {
    return "";
  }
  Formattable *obj = Formattable::fromUFormattable(fmt);
  CharString *charString = obj->internalGetCharString(*status);
  if(U_FAILURE(*status)) {
    return "";
  }
  if(charString == NULL) {
    *status = U_MEMORY_ALLOCATION_ERROR;
    return "";
  } else {
    if(len!=NULL) {
      *len = charString->length();
    }
    return charString->data();
  }
}

Project: icu
File: fmtable.cpp

ufmt_isNumeric(const UFormattable *fmt) {
  const Formattable *obj = Formattable::fromUFormattable(fmt);
  return obj->isNumeric();
}

Project: icu
File: fmtable.cpp

Formattable::populateDecimalQuantity(number::impl::DecimalQuantity& output, UErrorCode& status) const {
    if (fDecimalQuantity != nullptr) {
        output = *fDecimalQuantity;
        return;
    }

    switch (fType) {
        case kDouble:
            output.setToDouble(this->getDouble());
            output.roundToInfinity();
            break;
        case kLong:
            output.setToInt(this->getLong());
            break;
        case kInt64:
            output.setToLong(this->getInt64());
            break;
        default:
            // The formattable's value is not a numeric type.
            status = U_INVALID_STATE_ERROR;
    }
}

Project: icu
File: number_decimalquantity.cpp

int8_t DecimalQuantity::getDigitPos(int32_t position) const {
    if (usingBytes) {
        if (position < 0 || position >= precision) { return 0; }
        return fBCD.bcdBytes.ptr[position];
    } else {
        if (position < 0 || position >= 16) { return 0; }
        return (int8_t) ((fBCD.bcdLong >> (position * 4)) & 0xf);
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test13035_MultiCodePointPaddingInPattern() {
    IcuTestErrorCode status(*this, "Test13035_MultiCodePointPaddingInPattern");
    DecimalFormat df(u"a*'நி'###0b", status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    UnicodeString result;
    df.format(12, result.remove());
    // TODO(13034): Re-enable this test when support is added in ICU4C.
    //assertEquals("Multi-codepoint padding should not be split", u"aநிநி12b", result);
    df = DecimalFormat(u"a*\U0001F601###0b", status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    result = df.format(12, result.remove());
    assertEquals("Single-codepoint padding should not be split", u"a\U0001F601\U0001F60112b", result, true);
    df = DecimalFormat(u"a*''###0b", status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    result = df.format(12, result.remove());
    assertEquals("Quote should be escapable in padding syntax", "a''12b", result, true);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expectParseCurrency(const NumberFormat &fmt, const UChar* currency, double amount, const char *text) {
    ParsePosition ppos;
    UnicodeString utext = ctou(text);
    LocalPointer<CurrencyAmount> currencyAmount(fmt.parseCurrency(utext, ppos));
    if (!ppos.getIndex()) {
        errln(UnicodeString("Parse of ") + utext + " should have succeeded.");
        return;
    }
    UErrorCode status = U_ZERO_ERROR;

    char theInfo[100];
    sprintf(theInfo, "For locale %s, string \"%s\", currency ",
            fmt.getLocale(ULOC_ACTUAL_LOCALE, status).getBaseName(),
            text);
    u_austrcpy(theInfo+uprv_strlen(theInfo), currency);

    char theOperation[100];

    uprv_strcpy(theOperation, theInfo);
    uprv_strcat(theOperation, ", check amount:");
    assertTrue(theOperation, amount ==  currencyAmount->getNumber().getDouble(status));

    uprv_strcpy(theOperation, theInfo);
    uprv_strcat(theOperation, ", check currency:");
    assertEquals(theOperation, currency, currencyAmount->getISOCurrency());
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::compact() {
    if (usingBytes) {
        int32_t delta = 0;
        for (; delta < precision && fBCD.bcdBytes.ptr[delta] == 0; delta++);
        if (delta == precision) {
            // Number is zero
            setBcdToZero();
            return;
        } else {
            // Remove trailing zeros
            shiftRight(delta);
        }

        // Compute precision
        int32_t leading = precision - 1;
        for (; leading >= 0 && fBCD.bcdBytes.ptr[leading] == 0; leading--);
        precision = leading + 1;

        // Switch storage mechanism if possible
        if (precision <= 16) {
            switchStorage();
        }

    } else {
        if (fBCD.bcdLong == 0L) {
            // Number is zero
            setBcdToZero();
            return;
        }

        // Compact the number (remove trailing zeros)
        // TODO: Use a more efficient algorithm here and below. There is a logarithmic one.
        int32_t delta = 0;
        for (; delta < precision && getDigitPos(delta) == 0; delta++);
        fBCD.bcdLong >>= delta * 4;
        scale += delta;

        // Compute precision
        int32_t leading = precision - 1;
        for (; leading >= 0 && getDigitPos(leading) == 0; leading--);
        precision = leading + 1;
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test13391_chakmaParsing() {
    UErrorCode status = U_ZERO_ERROR;
    LocalPointer<DecimalFormat> df(dynamic_cast<DecimalFormat*>(
        NumberFormat::createInstance(Locale("ccp"), status)));
    if (df == nullptr) {
        dataerrln("%s %d Chakma df is null",  __FILE__, __LINE__);
        return;
    }
    const UChar* expected = u"\U00011137\U00011138,\U00011139\U0001113A\U0001113B";
    UnicodeString actual;
    df->format(12345, actual, status);
    assertSuccess("Should not fail when formatting in ccp", status);
    assertEquals("Should produce expected output in ccp", expected, actual);

    Formattable result;
    df->parse(expected, result, status);
    assertSuccess("Should not fail when parsing in ccp", status);
    assertEquals("Should parse to 12345 in ccp", 12345, result);

    const UChar* expectedScientific = u"\U00011137.\U00011139E\U00011138";
    UnicodeString actualScientific;
    df.adoptInstead(static_cast<DecimalFormat*>(
        NumberFormat::createScientificInstance(Locale("ccp"), status)));
    df->format(130, actualScientific, status);
    assertSuccess("Should not fail when formatting scientific in ccp", status);
    assertEquals("Should produce expected scientific output in ccp",
        expectedScientific, actualScientific);

    Formattable resultScientific;
    df->parse(expectedScientific, resultScientific, status);
    assertSuccess("Should not fail when parsing scientific in ccp", status);
    assertEquals("Should parse scientific to 130 in ccp", 130, resultScientific);
}

Project: icu
File: fmtable.cpp

Formattable::getArray(int32_t& count, UErrorCode& status) const 
{
    if (fType != kArray) {
        setError(status, U_INVALID_FORMAT_ERROR);
        count = 0;
        return NULL;
    }
    count = fValue.fArrayAndCount.fCount; 
    return fValue.fArrayAndCount.fArray;
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestCurrency(void)
{
    UErrorCode status = U_ZERO_ERROR;
    NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(Locale::getCanadaFrench(), status);
    if (U_FAILURE(status)) {
        dataerrln("Error calling NumberFormat::createCurrencyInstance()");
        return;
    }

    UnicodeString s; currencyFmt->format(1.50, s);
    logln((UnicodeString)"Un pauvre ici a..........." + s);
    if (!(s==CharsToUnicodeString("1,50\\u00A0$")))
        errln((UnicodeString)"FAIL: Expected 1,50<nbsp>$ but got " + s);
    delete currencyFmt;
    s.truncate(0);
    char loc[256]={0};
    int len = uloc_canonicalize("de_DE_PREEURO", loc, 256, &status);
    (void)len;  // Suppress unused variable warning.
    currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc),status);
    currencyFmt->format(1.50, s);
    logln((UnicodeString)"Un pauvre en Allemagne a.." + s);
    if (!(s==CharsToUnicodeString("1,50\\u00A0DM")))
        errln((UnicodeString)"FAIL: Expected 1,50<nbsp>DM but got " + s);
    delete currencyFmt;
    s.truncate(0);
    len = uloc_canonicalize("fr_FR_PREEURO", loc, 256, &status);
    currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
    currencyFmt->format(1.50, s);
    logln((UnicodeString)"Un pauvre en France a....." + s);
    if (!(s==CharsToUnicodeString("1,50\\u00A0F")))
        errln((UnicodeString)"FAIL: Expected 1,50<nbsp>F");
    delete currencyFmt;
    if (U_FAILURE(status))
        errln((UnicodeString)"FAIL: Status " + (int32_t)status);

    for(int i=0; i < UPRV_LENGTHOF(testCases); i++){
        status = U_ZERO_ERROR;
        const char *localeID = testCases[i][0];
        UnicodeString expected(testCases[i][1], -1, US_INV);
        expected = expected.unescape();
        s.truncate(0);
        char loc[256]={0};
        uloc_canonicalize(localeID, loc, 256, &status);
        currencyFmt = NumberFormat::createCurrencyInstance(Locale(loc), status);
        if(U_FAILURE(status)){
            errln("Could not create currency formatter for locale %s",localeID);
            continue;
        }
        currencyFmt->format(1150.50, s);
        if(s!=expected){
            errln(UnicodeString("FAIL: Expected: ")+expected
                    + UnicodeString(" Got: ") + s
                    + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
        }
        if (U_FAILURE(status)){
            errln((UnicodeString)"FAIL: Status " + (int32_t)status);
        }
        delete currencyFmt;
    }
}

Project: icu
File: fmtable.cpp

ufmt_getDouble(UFormattable *fmt, UErrorCode *status) {
  Formattable *obj = Formattable::fromUFormattable(fmt);

  return obj->getDouble(*status);
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::_setToInt(int32_t n) {
    if (n == INT32_MIN) {
        readLongToBcd(-static_cast<int64_t>(n));
    } else {
        readIntToBcd(n);
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestAvailableNumberingSystems() {
    UErrorCode status = U_ZERO_ERROR;
    StringEnumeration *availableNumberingSystems = NumberingSystem::getAvailableNames(status);
    CHECK_DATA(status, "NumberingSystem::getAvailableNames()")

    int32_t nsCount = availableNumberingSystems->count(status);
    if ( nsCount < 74 ) {
        errln("FAIL: Didn't get as many numbering systems as we had hoped for. Need at least 74, got %d",nsCount);
    }

    /* A relatively simple test of the API.  We call getAvailableNames() and cycle through */
    /* each name returned, attempting to create a numbering system based on that name and  */
    /* verifying that the name returned from the resulting numbering system is the same    */
    /* one that we initially thought.                                                      */

    int32_t len;
    for ( int32_t i = 0 ; i < nsCount ; i++ ) {
        const char *nsname = availableNumberingSystems->next(&len,status);
        NumberingSystem* ns = NumberingSystem::createInstanceByName(nsname,status);
        logln("OK for ns = %s",nsname);
        if ( uprv_strcmp(nsname,ns->getName()) ) {
            errln("FAIL: Numbering system name didn't match for name = %s\n",nsname);
        }

        delete ns;
    }

    delete availableNumberingSystems;
}

Project: icu
File: number_decimalquantity.cpp

int64_t DecimalQuantity::toLong(bool truncateIfOverflow) const {
    // NOTE: Call sites should be guarded by fitsInLong(), like this:
    // if (dq.fitsInLong()) { /* use dq.toLong() */ } else { /* use some fallback */ }
    // Fallback behavior upon truncateIfOverflow is to truncate at 17 digits.
    uint64_t result = 0L;
    int32_t upperMagnitude = std::min(scale + precision, lOptPos) - 1;
    if (truncateIfOverflow) {
        upperMagnitude = std::min(upperMagnitude, 17);
    }
    for (int32_t magnitude = upperMagnitude; magnitude >= 0; magnitude--) {
        result = result * 10 + getDigitPos(magnitude - scale);
    }
    if (isNegative()) {
        return static_cast<int64_t>(0LL - result); // i.e., -result
    }
    return static_cast<int64_t>(result);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test10727_RoundingZero() {
    IcuTestErrorCode status(*this, "Test10727_RoundingZero");
    DecimalQuantity dq;
    dq.setToDouble(-0.0);
    assertTrue("", dq.isNegative());
    dq.roundToMagnitude(0, UNUM_ROUND_HALFEVEN, status);
    assertTrue("", dq.isNegative());
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestInt64() {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormat fmt("#.#E0",status);
    if (U_FAILURE(status)) {
        dataerrln("Error creating DecimalFormat - %s", u_errorName(status));
        return;
    }
    fmt.setMaximumFractionDigits(20);
    if (U_SUCCESS(status)) {
        expect(fmt, (Formattable)(int64_t)0, "0E0");
        expect(fmt, (Formattable)(int64_t)-1, "-1E0");
        expect(fmt, (Formattable)(int64_t)1, "1E0");
        expect(fmt, (Formattable)(int64_t)2147483647, "2.147483647E9");
        expect(fmt, (Formattable)((int64_t)-2147483647-1), "-2.147483648E9");
        expect(fmt, (Formattable)(int64_t)U_INT64_MAX, "9.223372036854775807E18");
        expect(fmt, (Formattable)(int64_t)U_INT64_MIN, "-9.223372036854775808E18");
    }

    // also test digitlist
/*    int64_t int64max = U_INT64_MAX;
    int64_t int64min = U_INT64_MIN;
    const char* int64maxstr = "9223372036854775807";
    const char* int64minstr = "-9223372036854775808";
    UnicodeString fail("fail: ");

    // test max int64 value
    DigitList dl;
    setFromString(dl, int64maxstr);
    {
        if (!dl.fitsIntoInt64(FALSE)) {
            errln(fail + int64maxstr + " didn't fit");
        }
        int64_t int64Value = dl.getInt64();
        if (int64Value != int64max) {
            errln(fail + int64maxstr);
        }
        dl.set(int64Value);
        int64Value = dl.getInt64();
        if (int64Value != int64max) {
            errln(fail + int64maxstr);
        }
    }
    // test negative of max int64 value (1 shy of min int64 value)
    dl.fIsPositive = FALSE;
    {
        if (!dl.fitsIntoInt64(FALSE)) {
            errln(fail + "-" + int64maxstr + " didn't fit");
        }
        int64_t int64Value = dl.getInt64();
        if (int64Value != -int64max) {
            errln(fail + "-" + int64maxstr);
        }
        dl.set(int64Value);
        int64Value = dl.getInt64();
        if (int64Value != -int64max) {
            errln(fail + "-" + int64maxstr);
        }
    }
    // test min int64 value
    setFromString(dl, int64minstr);
    {
        if (!dl.fitsIntoInt64(FALSE)) {
            errln(fail + "-" + int64minstr + " didn't fit");
        }
        int64_t int64Value = dl.getInt64();
        if (int64Value != int64min) {
            errln(fail + int64minstr);
        }
        dl.set(int64Value);
        int64Value = dl.getInt64();
        if (int64Value != int64min) {
            errln(fail + int64minstr);
        }
    }
    // test negative of min int 64 value (1 more than max int64 value)
    dl.fIsPositive = TRUE; // won't fit
    {
        if (dl.fitsIntoInt64(FALSE)) {
            errln(fail + "-(" + int64minstr + ") didn't fit");
        }
    }*/
}

Project: icu
File: fmtable.cpp

Formattable::Formattable(StringPiece number, UErrorCode &status) {
    init();
    setDecimalNumber(number, status);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestUFormattable(void) {
  {
    // test that a default formattable is equal to Formattable()
    UErrorCode status = U_ZERO_ERROR;
    LocalUFormattablePointer defaultUFormattable(ufmt_open(&status));
    assertSuccess("calling umt_open", status);
    Formattable defaultFormattable;
    assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
               (defaultFormattable
                == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
    assertTrue((UnicodeString)"comparing ufmt_open() with Formattable()",
               (defaultFormattable
                == *(Formattable::fromUFormattable(defaultUFormattable.getAlias()))));
    assertTrue((UnicodeString)"comparing Formattable() round tripped through UFormattable",
               (defaultFormattable
                == *(Formattable::fromUFormattable(defaultFormattable.toUFormattable()))));
    assertTrue((UnicodeString)"comparing &Formattable() round tripped through UFormattable",
               ((&defaultFormattable)
                == Formattable::fromUFormattable(defaultFormattable.toUFormattable())));
    assertFalse((UnicodeString)"comparing &Formattable() with ufmt_open()",
               ((&defaultFormattable)
                == Formattable::fromUFormattable(defaultUFormattable.getAlias())));
    testFormattableAsUFormattable(__FILE__, __LINE__, defaultFormattable);
  }
  // test some random Formattables
  {
    Formattable f(ucal_getNow(), Formattable::kIsDate);
    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
  }
  {
    Formattable f((double)1.61803398874989484820); // golden ratio
    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
  }
  {
    Formattable f((int64_t)80994231587905127LL); // weight of the moon, in kilotons http://solarsystem.nasa.gov/planets/profile.cfm?Display=Facts&Object=Moon
    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
  }
  {
    Formattable f((int32_t)4); // random number, source: http://www.xkcd.com/221/
    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
  }
  {
    Formattable f("Hello world."); // should be invariant?
    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
  }
  {
    UErrorCode status2 = U_ZERO_ERROR;
    Formattable f(StringPiece("73476730924573500000000.0"), status2); // weight of the moon, kg
    assertSuccess("Constructing a StringPiece", status2);
    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
  }
  {
    UErrorCode status2 = U_ZERO_ERROR;
    UObject *obj = new Locale();
    Formattable f(obj);
    assertSuccess("Constructing a Formattable from a default constructed Locale()", status2);
    testFormattableAsUFormattable(__FILE__, __LINE__,  f);
  }
  {
    const Formattable array[] = {
      Formattable(ucal_getNow(), Formattable::kIsDate),
      Formattable((int32_t)4),
      Formattable((double)1.234),
    };

    Formattable fa(array, 3);
    testFormattableAsUFormattable(__FILE__, __LINE__, fa);
  }
}

Project: icu
File: fmtable.cpp

Formattable::adoptString(UnicodeString* stringToAdopt)
{
    dispose();
    fType = kString;
    fValue.fString = stringToAdopt;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestAccountingCurrency() {
    UErrorCode status = U_ZERO_ERROR;
    UNumberFormatStyle style = UNUM_CURRENCY_ACCOUNTING;

    expect(NumberFormat::createInstance("en_US", style, status),
        (Formattable)(double)1234.5, "$1,234.50", TRUE, status);
    expect(NumberFormat::createInstance("en_US", style, status),
        (Formattable)(double)-1234.5, "($1,234.50)", TRUE, status);
    expect(NumberFormat::createInstance("en_US", style, status),
        (Formattable)(double)0, "$0.00", TRUE, status);
    expect(NumberFormat::createInstance("en_US", style, status),
        (Formattable)(double)-0.2, "($0.20)", TRUE, status);
    expect(NumberFormat::createInstance("ja_JP", style, status),
        (Formattable)(double)10000, UnicodeString("\\uFFE510,000").unescape(), TRUE, status);
    expect(NumberFormat::createInstance("ja_JP", style, status),
        (Formattable)(double)-1000.5, UnicodeString("(\\uFFE51,000)").unescape(), FALSE, status);
    expect(NumberFormat::createInstance("de_DE", style, status),
        (Formattable)(double)-23456.7, UnicodeString("-23.456,70\\u00A0\\u20AC").unescape(), TRUE, status);
}

Project: icu
File: number_decimalquantity.cpp

void DecimalQuantity::convertToAccurateDouble() {
    U_ASSERT(origDouble != 0);
    int32_t delta = origDelta;

    // Call the slow oracle function (Double.toString in Java, DoubleToAscii in C++).
    char buffer[DoubleToStringConverter::kBase10MaximalLength + 1];
    bool sign; // unused; always positive
    int32_t length;
    int32_t point;
    DoubleToStringConverter::DoubleToAscii(
        origDouble,
        DoubleToStringConverter::DtoaMode::SHORTEST,
        0,
        buffer,
        sizeof(buffer),
        &sign,
        &length,
        &point
    );

    setBcdToZero();
    readDoubleConversionToBcd(buffer, length, point);
    scale += delta;
    explicitExactDouble = true;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestSurrogateSupport(void) {
    UErrorCode status = U_ZERO_ERROR;
    DecimalFormatSymbols custom(Locale::getUS(), status);
    CHECK(status, "DecimalFormatSymbols constructor");

    custom.setSymbol(DecimalFormatSymbols::kDecimalSeparatorSymbol, "decimal");
    custom.setSymbol(DecimalFormatSymbols::kPlusSignSymbol, "plus");
    custom.setSymbol(DecimalFormatSymbols::kMinusSignSymbol, " minus ");
    custom.setSymbol(DecimalFormatSymbols::kExponentialSymbol, "exponent");

    UnicodeString patternStr("*\\U00010000##.##", "");
    patternStr = patternStr.unescape();
    UnicodeString expStr("\\U00010000\\U00010000\\U00010000\\U000100000", "");
    expStr = expStr.unescape();
    expect2(new DecimalFormat(patternStr, custom, status),
           int32_t(0), expStr, status);

    status = U_ZERO_ERROR;
    expect2(new DecimalFormat("*^##.##", custom, status),
           int32_t(0), "^^^^0", status);
    status = U_ZERO_ERROR;
    expect2(new DecimalFormat("##.##", custom, status),
           -1.3, " minus 1decimal3", status);
    status = U_ZERO_ERROR;
    expect2(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
           int32_t(0), "0decimal0exponent0 g-m/s^2", status);
    status = U_ZERO_ERROR;
    expect(new DecimalFormat("##0.0####E0 'g-m/s^2'", custom, status),
           1.0/3, "333decimal333exponent minus 3 g-m/s^2", status);
    status = U_ZERO_ERROR;
    expect2(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
           int32_t(0), "0decimal0 g-m/s^2", status);
    status = U_ZERO_ERROR;
    expect(new DecimalFormat("##0.0#### 'g-m/s^2'", custom, status),
           1.0/3, "0decimal33333 g-m/s^2", status);

    UnicodeString zero((UChar32)0x10000);
    UnicodeString one((UChar32)0x10001);
    UnicodeString two((UChar32)0x10002);
    UnicodeString five((UChar32)0x10005);
    custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, zero);
    custom.setSymbol(DecimalFormatSymbols::kOneDigitSymbol, one);
    custom.setSymbol(DecimalFormatSymbols::kTwoDigitSymbol, two);
    custom.setSymbol(DecimalFormatSymbols::kFiveDigitSymbol, five);
    expStr = UnicodeString("\\U00010001decimal\\U00010002\\U00010005\\U00010000", "");
    expStr = expStr.unescape();
    status = U_ZERO_ERROR;
    expect2(new DecimalFormat("##0.000", custom, status),
           1.25, expStr, status);

    custom.setSymbol(DecimalFormatSymbols::kZeroDigitSymbol, (UChar)0x30);
    custom.setSymbol(DecimalFormatSymbols::kCurrencySymbol, "units of money");
    custom.setSymbol(DecimalFormatSymbols::kMonetarySeparatorSymbol, "money separator");
    patternStr = UNICODE_STRING_SIMPLE("0.00 \\u00A4' in your bank account'");
    patternStr = patternStr.unescape();
    expStr = UnicodeString(" minus 20money separator00 units of money in your bank account", "");
    status = U_ZERO_ERROR;
    expect2(new DecimalFormat(patternStr, custom, status),
           int32_t(-20), expStr, status);

    custom.setSymbol(DecimalFormatSymbols::kPercentSymbol, "percent");
    patternStr = "'You''ve lost ' -0.00 %' of your money today'";
    patternStr = patternStr.unescape();
    expStr = UnicodeString(" minus You've lost   minus 2000decimal00 percent of your money today", "");
    status = U_ZERO_ERROR;
    expect2(new DecimalFormat(patternStr, custom, status),
           int32_t(-20), expStr, status);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCurrencyUnit(void){
    UErrorCode ec = U_ZERO_ERROR;
    static const UChar USD[]  = u"USD";
    static const char USD8[]  =  "USD";
    static const UChar BAD[]  = u"???";
    static const UChar BAD2[] = u"??A";
    static const UChar XXX[]  = u"XXX";
    static const char XXX8[]  =  "XXX";
    CurrencyUnit cu(USD, ec);
    assertSuccess("CurrencyUnit", ec);

    assertEquals("getISOCurrency()", USD, cu.getISOCurrency());
    assertEquals("getSubtype()", USD8, cu.getSubtype());

    CurrencyUnit cu2(cu);
    if (!(cu2 == cu)){
        errln("CurrencyUnit copy constructed object should be same");
    }

    CurrencyUnit * cu3 = (CurrencyUnit *)cu.clone();
    if (!(*cu3 == cu)){
        errln("CurrencyUnit cloned object should be same");
    }
    CurrencyUnit bad(BAD, ec);
    assertSuccess("CurrencyUnit", ec);
    if (cu.getIndex() == bad.getIndex()) {
        errln("Indexes of different currencies should differ.");
    }
    CurrencyUnit bad2(BAD2, ec);
    assertSuccess("CurrencyUnit", ec);
    if (bad2.getIndex() != bad.getIndex()) {
        errln("Indexes of unrecognized currencies should be the same.");
    }
    if (bad == bad2) {
        errln("Different unrecognized currencies should not be equal.");
    }
    bad = bad2;
    if (bad != bad2) {
        errln("Currency unit assignment should be the same.");
    }
    delete cu3;

    // Test default constructor
    CurrencyUnit def;
    assertEquals("Default currency", XXX, def.getISOCurrency());
    assertEquals("Default currency as subtype", XXX8, def.getSubtype());

    // Test slicing
    MeasureUnit sliced1 = cu;
    MeasureUnit sliced2 = cu;
    assertEquals("Subtype after slicing 1", USD8, sliced1.getSubtype());
    assertEquals("Subtype after slicing 2", USD8, sliced2.getSubtype());
    CurrencyUnit restored1(sliced1, ec);
    CurrencyUnit restored2(sliced2, ec);
    assertSuccess("Restoring from MeasureUnit", ec);
    assertEquals("Subtype after restoring 1", USD8, restored1.getSubtype());
    assertEquals("Subtype after restoring 2", USD8, restored2.getSubtype());
    assertEquals("ISO Code after restoring 1", USD, restored1.getISOCurrency());
    assertEquals("ISO Code after restoring 2", USD, restored2.getISOCurrency());

    // Test copy constructor failure
    LocalPointer<MeasureUnit> meter(MeasureUnit::createMeter(ec));
    assertSuccess("Creating meter", ec);
    CurrencyUnit failure(*meter, ec);
    assertEquals("Copying from meter should fail", ec, U_ILLEGAL_ARGUMENT_ERROR);
    assertEquals("Copying should not give uninitialized ISO code", u"", failure.getISOCurrency());
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestCases() {
    UErrorCode ec = U_ZERO_ERROR;
    TextFile reader("NumberFormatTestCases.txt", "UTF8", ec);
    if (U_FAILURE(ec)) {
        dataerrln("Couldn't open NumberFormatTestCases.txt");
        return;
    }
    TokenIterator tokens(&reader);

    Locale loc("en", "US", "");
    DecimalFormat *ref = 0, *fmt = 0;
    MeasureFormat *mfmt = 0;
    UnicodeString pat, tok, mloc, str, out, where, currAmt;
    Formattable n;

    for (;;) {
        ec = U_ZERO_ERROR;
        if (!tokens.next(tok, ec)) {
            break;
        }
        where = UnicodeString("(") + tokens.getLineNumber() + ") ";
        int32_t cmd = keywordIndex(tok);
        switch (cmd) {
        case 0:
            // ref= <reference pattern>
            if (!tokens.next(tok, ec)) goto error;
            delete ref;
            ref = new DecimalFormat(tok,
                      new DecimalFormatSymbols(Locale::getUS(), ec), ec);
            if (U_FAILURE(ec)) {
                dataerrln("Error constructing DecimalFormat");
                goto error;
            }
            break;
        case 1:
            // loc= <locale>
            if (!tokens.next(tok, ec)) goto error;
            loc = Locale::createFromName(CharString().appendInvariantChars(tok, ec).data());
            break;
        case 2: // f:
        case 3: // fp:
        case 4: // rt:
        case 5: // p:
            if (!tokens.next(tok, ec)) goto error;
            if (tok != "-") {
                pat = tok;
                delete fmt;
                fmt = new DecimalFormat(pat, new DecimalFormatSymbols(loc, ec), ec);
                if (U_FAILURE(ec)) {
                    errln("FAIL: " + where + "Pattern \"" + pat + "\": " + u_errorName(ec));
                    ec = U_ZERO_ERROR;
                    if (!tokens.next(tok, ec)) goto error;
                    if (!tokens.next(tok, ec)) goto error;
                    if (cmd == 3) {
                        if (!tokens.next(tok, ec)) goto error;
                    }
                    continue;
                }
            }
            if (cmd == 2 || cmd == 3 || cmd == 4) {
                // f: <pattern or '-'> <number> <exp. string>
                // fp: <pattern or '-'> <number> <exp. string> <exp. number>
                // rt: <pattern or '-'> <number> <string>
                UnicodeString num;
                if (!tokens.next(num, ec)) goto error;
                if (!tokens.next(str, ec)) goto error;
                ref->parse(num, n, ec);
                assertSuccess("parse", ec);
                assertEquals(where + "\"" + pat + "\".format(" + num + ")",
                             str, fmt->format(n, out.remove(), ec));
                assertSuccess("format", ec);
                if (cmd == 3) { // fp:
                    if (!tokens.next(num, ec)) goto error;
                    ref->parse(num, n, ec);
                    assertSuccess("parse", ec);
                }
                if (cmd != 2) { // != f:
                    Formattable m;
                    fmt->parse(str, m, ec);
                    assertSuccess("parse", ec);
                    assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
                                 n, m);
                }
            }
            // p: <pattern or '-'> <string to parse> <exp. number>
            else {
                UnicodeString expstr;
                if (!tokens.next(str, ec)) goto error;
                if (!tokens.next(expstr, ec)) goto error;
                Formattable exp, n;
                ref->parse(expstr, exp, ec);
                assertSuccess("parse", ec);
                fmt->parse(str, n, ec);
                assertSuccess("parse", ec);
                assertEquals(where + "\"" + pat + "\".parse(\"" + str + "\")",
                             exp, n);
            }
            break;
        case 8: // fpc:
            if (!tokens.next(tok, ec)) goto error;
            if (tok != "-") {
                mloc = tok;
                delete mfmt;
                mfmt = MeasureFormat::createCurrencyFormat(
                    Locale::createFromName(
                        CharString().appendInvariantChars(mloc, ec).data()), ec);
                if (U_FAILURE(ec)) {
                    errln("FAIL: " + where + "Loc \"" + mloc + "\": " + u_errorName(ec));
                    ec = U_ZERO_ERROR;
                    if (!tokens.next(tok, ec)) goto error;
                    if (!tokens.next(tok, ec)) goto error;
                    if (!tokens.next(tok, ec)) goto error;
                    continue;
                }
            } else if (mfmt == NULL) {
                errln("FAIL: " + where + "Loc \"" + mloc + "\": skip case using previous locale, no valid MeasureFormat");
                if (!tokens.next(tok, ec)) goto error;
                if (!tokens.next(tok, ec)) goto error;
                if (!tokens.next(tok, ec)) goto error;
                continue;
            }
            // fpc: <loc or '-'> <curr.amt> <exp. string> <exp. curr.amt>
            if (!tokens.next(currAmt, ec)) goto error;
            if (!tokens.next(str, ec)) goto error;
            parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
            if (assertSuccess("parseCurrencyAmount", ec)) {
                assertEquals(where + "getCurrencyFormat(" + mloc + ").format(" + currAmt + ")",
                             str, mfmt->format(n, out.remove(), ec));
                assertSuccess("format", ec);
            }
            if (!tokens.next(currAmt, ec)) goto error;
            parseCurrencyAmount(currAmt, *ref, (UChar)0x2F/*'/'*/, n, ec);
            if (assertSuccess("parseCurrencyAmount", ec)) {
                Formattable m;

                mfmt->parseObject(str, m, ec);
                if (assertSuccess("parseCurrency", ec)) {
                    assertEquals(where + "getCurrencyFormat(" + mloc + ").parse(\"" + str + "\")",
                                 n, m);
                } else {
                    errln("FAIL: source " + str);
                }
            }
            break;
        case 6:
            // perr: <pattern or '-'> <invalid string>
            errln("FAIL: Under construction");
            goto done;
        case 7: {
            // pat: <pattern> <exp. toPattern, or '-' or 'err'>
            UnicodeString testpat;
            UnicodeString exppat;
            if (!tokens.next(testpat, ec)) goto error;
            if (!tokens.next(exppat, ec)) goto error;
            UBool err = exppat == "err";
            UBool existingPat = FALSE;
            if (testpat == "-") {
                if (err) {
                    errln("FAIL: " + where + "Invalid command \"pat: - err\"");
                    continue;
                }
                existingPat = TRUE;
                testpat = pat;
            }
            if (exppat == "-") exppat = testpat;
            DecimalFormat* f = 0;
            UErrorCode ec2 = U_ZERO_ERROR;
            if (existingPat) {
                f = fmt;
            } else {
                f = new DecimalFormat(testpat, ec2);
            }
            if (U_SUCCESS(ec2)) {
                if (err) {
                    errln("FAIL: " + where + "Invalid pattern \"" + testpat +
                          "\" was accepted");
                } else {
                    UnicodeString pat2;
                    assertEquals(where + "\"" + testpat + "\".toPattern()",
                                 exppat, f->toPattern(pat2));
                }
            } else {
                if (err) {
                    logln("Ok: " + where + "Invalid pattern \"" + testpat +
                          "\" failed: " + u_errorName(ec2));
                } else {
                    errln("FAIL: " + where + "Valid pattern \"" + testpat +
                          "\" failed: " + u_errorName(ec2));
                }
            }
            if (!existingPat) delete f;
            } break;
        case -1:
            errln("FAIL: " + where + "Unknown command \"" + tok + "\"");
            goto done;
        }
    }
    goto done;

 error:
    if (U_SUCCESS(ec)) {
        errln("FAIL: Unexpected EOF");
    } else {
        errcheckln(ec, "FAIL: " + where + "Unexpected " + u_errorName(ec));
    }

 done:
    delete mfmt;
    delete fmt;
    delete ref;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test13777_ParseLongNameNonCurrencyMode() {
    IcuTestErrorCode status(*this, "Test13777_ParseLongNameNonCurrencyMode");

    LocalPointer<NumberFormat> df(
        NumberFormat::createInstance("en-us", UNumberFormatStyle::UNUM_CURRENCY_PLURAL, status), status);
    if (!assertSuccess("", status, true, __FILE__, __LINE__)) { return; }
    expect2(*df, 1.5, u"1.50 US dollars");
}

Project: icu
File: numfmtst.cpp

    virtual UnicodeString& format(const Formattable& , UnicodeString& appendTo, FieldPosition& , UErrorCode& ) const {
        return appendTo;
    }

Project: icu
File: fmtable.cpp

Formattable::getString(UErrorCode& status) const 
{
    if (fType != kString) {
        setError(status, U_INVALID_FORMAT_ERROR);
        return *getBogus();
    }
    if (fValue.fString == NULL) {
        setError(status, U_MEMORY_ALLOCATION_ERROR);
        return *getBogus();
    }
    return *fValue.fString;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expect2(NumberFormat& fmt, const Formattable& n, const UnicodeString& str) {
    // Don't round-trip format test, since we explicitly do it
    expect(fmt, n, str, FALSE);
    expect(fmt, str, n);
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestJB3832(){
    const char* localeID = "pt_PT@currency=PTE";
    Locale loc(localeID);
    UErrorCode status = U_ZERO_ERROR;
    UnicodeString expected(CharsToUnicodeString("1,150$50\\u00A0\\u200B")); // per cldrbug 7670
    UnicodeString s;
    NumberFormat* currencyFmt = NumberFormat::createCurrencyInstance(loc, status);
    if(U_FAILURE(status)){
        dataerrln("Could not create currency formatter for locale %s - %s", localeID, u_errorName(status));
        return;
    }
    currencyFmt->format(1150.50, s);
    if(s!=expected){
        errln(UnicodeString("FAIL: Expected: ")+expected
                + UnicodeString(" Got: ") + s
                + UnicodeString( " for locale: ")+ UnicodeString(localeID) );
    }
    if (U_FAILURE(status)){
        errln("FAIL: Status %s", u_errorName(status));
    }
    delete currencyFmt;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestPerMill() {
    UErrorCode ec = U_ZERO_ERROR;
    UnicodeString str;
    DecimalFormat fmt(ctou("###.###\\u2030"), ec);
    if (!assertSuccess("DecimalFormat ct", ec)) return;
    assertEquals("0.4857 x ###.###\\u2030",
                 ctou("485.7\\u2030"), fmt.format(0.4857, str), true);

    DecimalFormatSymbols sym(Locale::getUS(), ec);
    if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
        return;
    }
    sym.setSymbol(DecimalFormatSymbols::kPerMillSymbol, ctou("m"));
    DecimalFormat fmt2("", sym, ec);
    if (!assertSuccess("", ec, true, __FILE__, __LINE__)) {
        return;
    }
    fmt2.applyLocalizedPattern("###.###m", ec);
    if (!assertSuccess("setup", ec)) return;
    str.truncate(0);
    assertEquals("0.4857 x ###.###m",
                 "485.7m", fmt2.format(0.4857, str));
}

Project: icu
File: number_decimalquantity.cpp

int32_t DecimalQuantity::fractionCount() const {
    return -getLowerDisplayMagnitude();
}

Project: icu
File: fmtable.cpp

Formattable::adoptDecimalQuantity(DecimalQuantity *dq) {
    if (fDecimalQuantity != NULL) {
        delete fDecimalQuantity;
    }
    fDecimalQuantity = dq;
    if (dq == NULL) { // allow adoptDigitList(NULL) to clear
        return;
    }

    // Set the value into the Union of simple type values.
    // Cannot use the set() functions because they would delete the fDecimalNum value.
    if (fDecimalQuantity->fitsInLong()) {
        fValue.fInt64 = fDecimalQuantity->toLong();
        if (fValue.fInt64 <= INT32_MAX && fValue.fInt64 >= INT32_MIN) {
            fType = kLong;
        } else {
            fType = kInt64;
        }
    } else {
        fType = kDouble;
        fValue.fDouble = fDecimalQuantity->toDouble();
    }
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestCurrencyParsing() {
    static const char* DATA[][6] = {
        // the data are:
        // locale,
        // currency amount to be formatted,
        // currency ISO code to be formatted,
        // format result using CURRENCYSTYLE,
        // format result using ISOCURRENCYSTYLE,
        // format result using PLURALCURRENCYSTYLE,
        {"en_US", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00 US dollars"},
        {"pa_IN", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\u0a2f\\u0a42.\\u0a10\\u0a38. \\u0a21\\u0a3e\\u0a32\\u0a30"},
        {"es_AR", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 d\\u00f3lar estadounidense"},
        {"ar_EG", "1", "USD", "\\u0661\\u066b\\u0660\\u0660\\u00a0US$", "\\u0661\\u066b\\u0660\\u0660\\u00a0USD", "\\u0661\\u066b\\u0660\\u0660 \\u062f\\u0648\\u0644\\u0627\\u0631 \\u0623\\u0645\\u0631\\u064a\\u0643\\u064a"},
        {"fa_CA", "1", "USD", "\\u200e$\\u06f1\\u066b\\u06f0\\u06f0", "\\u200eUSD\\u06f1\\u066b\\u06f0\\u06f0", "\\u06f1\\u066b\\u06f0\\u06f0 \\u062f\\u0644\\u0627\\u0631 \\u0627\\u0645\\u0631\\u06cc\\u06a9\\u0627"},
        {"he_IL", "1", "USD", "\\u200f1.00\\u00a0$", "\\u200f1.00\\u00a0USD", "1.00 \\u05d3\\u05d5\\u05dc\\u05e8 \\u05d0\\u05de\\u05e8\\u05d9\\u05e7\\u05d0\\u05d9"},
        {"hr_HR", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 ameri\\u010Dkih dolara"},
        {"id_ID", "1", "USD", "US$\\u00A01,00", "USD\\u00A01,00", "1,00 Dolar Amerika Serikat"},
        {"it_IT", "1", "USD", "1,00\\u00a0USD", "1,00\\u00a0USD", "1,00 dollari statunitensi"},
        {"ko_KR", "1", "USD", "US$\\u00A01.00", "USD\\u00A01.00", "1.00 \\ubbf8\\uad6d \\ub2ec\\ub7ec"},
        {"ja_JP", "1", "USD", "$1.00", "USD\\u00A01.00", "1.00\\u00A0\\u7c73\\u30c9\\u30eb"},
        {"zh_CN", "1", "CNY", "\\uFFE51.00", "CNY\\u00A001.00", "1.00\\u00A0\\u4EBA\\u6C11\\u5E01"},
        {"zh_TW", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
        {"zh_Hant", "1", "CNY", "CN\\u00A51.00", "CNY\\u00A01.00", "1.00 \\u4eba\\u6c11\\u5e63"},
        {"zh_Hant", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1 \\u65E5\\u5713"},
        {"ja_JP", "1", "JPY", "\\uFFE51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
        // ICU 62 requires #parseCurrency() to recognize variants when parsing
        // {"ja_JP", "1", "JPY", "\\u00A51.00", "JPY\\u00A01.00", "1\\u00A0\\u5186"},
        {"ru_RU", "1", "RUB", "1,00\\u00A0\\u00A0\\u20BD", "1,00\\u00A0\\u00A0RUB", "1,00 \\u0440\\u043E\\u0441\\u0441\\u0438\\u0439\\u0441\\u043A\\u043E\\u0433\\u043E \\u0440\\u0443\\u0431\\u043B\\u044F"}
    };
    static const UNumberFormatStyle currencyStyles[] = {
        UNUM_CURRENCY,
        UNUM_CURRENCY_ISO,
        UNUM_CURRENCY_PLURAL
    };
    static const char* currencyStyleNames[] = {
      "UNUM_CURRENCY",
      "UNUM_CURRENCY_ISO",
      "UNUM_CURRENCY_PLURAL"
    };

#ifdef NUMFMTST_CACHE_DEBUG
int deadloop = 0;
for (;;) {
    printf("loop: %d\n", deadloop++);
#endif
    for (uint32_t i=0; i< UPRV_LENGTHOF(DATA); ++i) {  /* i = test case #  - should be i=0*/
      for (int32_t kIndex = 2; kIndex < UPRV_LENGTHOF(currencyStyles); ++kIndex) {
        UNumberFormatStyle k = currencyStyles[kIndex]; /* k = style */
        const char* localeString = DATA[i][0];
        double numberToBeFormat = atof(DATA[i][1]);
        const char* currencyISOCode = DATA[i][2];
        Locale locale(localeString);
        UErrorCode status = U_ZERO_ERROR;
        NumberFormat* numFmt = NumberFormat::createInstance(locale, k, status);
        logln("#%d NumberFormat(%s, %s) Currency=%s\n",
              i, localeString, currencyStyleNames[kIndex],
              currencyISOCode);

        if (U_FAILURE(status)) {
            delete numFmt;
            dataerrln((UnicodeString)"can not create instance, locale:" + localeString + ", style: " + k + " - " + u_errorName(status));
            continue;
        }
        UChar currencyCode[4];
        u_charsToUChars(currencyISOCode, currencyCode, 4);
        numFmt->setCurrency(currencyCode, status);
        if (U_FAILURE(status)) {
            delete numFmt;
            errln((UnicodeString)"can not set currency:" + currencyISOCode);
            continue;
        }

        UnicodeString strBuf;
        numFmt->format(numberToBeFormat, strBuf);
        int resultDataIndex = 3 + kIndex;
        // DATA[i][resultDataIndex] is the currency format result
        // using 'k' currency style.
        UnicodeString formatResult = ctou(DATA[i][resultDataIndex]);
        if (strBuf.compare(formatResult)) {
            errln("FAIL: Expected " + formatResult + " actual: " + strBuf);
        }
        // test parsing, and test parsing for all currency formats.
        // NOTE: ICU 62 requires that the currency format match the pattern in strict mode.
        numFmt->setLenient(TRUE);
        for (int j = 3; j < 6; ++j) {
            // DATA[i][3] is the currency format result using
            // CURRENCYSTYLE formatter.
            // DATA[i][4] is the currency format result using
            // ISOCURRENCYSTYLE formatter.
            // DATA[i][5] is the currency format result using
            // PLURALCURRENCYSTYLE formatter.
            UnicodeString oneCurrencyFormatResult = ctou(DATA[i][j]);
            UErrorCode status = U_ZERO_ERROR;
            Formattable parseResult;
            logln("parse(%s)", DATA[i][j]);
            numFmt->parse(oneCurrencyFormatResult, parseResult, status);
            if (U_FAILURE(status) ||
                (parseResult.getType() == Formattable::kDouble &&
                 parseResult.getDouble() != numberToBeFormat) ||
                (parseResult.getType() == Formattable::kLong &&
                 parseResult.getLong() != numberToBeFormat)) {
                errln((UnicodeString)"FAIL: NumberFormat(" + localeString +", " + currencyStyleNames[kIndex] +
                      "), Currency="+currencyISOCode+", parse("+DATA[i][j]+") returned error " + (UnicodeString)u_errorName(status)+".  Testcase: data[" + i + "][" + currencyStyleNames[j-3] +"="+j+"]");
                if (parseResult.getType() == Formattable::kDouble) {
                    errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (double): " +parseResult.getDouble());
                } else {
                    errln((UnicodeString)"expected: " + numberToBeFormat + "; actual (long): " +parseResult.getLong());
                }
                errln((UnicodeString)" round-trip would be: " + strBuf);
            }
        }
        delete numFmt;
      }
    }
#ifdef NUMFMTST_CACHE_DEBUG
}
#endif
}

Project: icu
File: numfmtst.cpp

    virtual UnicodeString& format(int32_t ,UnicodeString& appendTo,FieldPosition& ) const {
        return appendTo.append((UChar)0x0033);
    }

Project: icu
File: numfmtst.cpp

void NumberFormatTest::expect(NumberFormat& fmt, const Formattable& n,
                              const UnicodeString& exp, UBool rt) {
    UnicodeString saw;
    FieldPosition pos;
    UErrorCode status = U_ZERO_ERROR;
    fmt.format(n, saw, pos, status);
    CHECK(status, "NumberFormat::format");
    UnicodeString pat;
    ((DecimalFormat*) &fmt)->toPattern(pat);
    if (saw == exp) {
        logln(UnicodeString("Ok   ") + toString(n) + " x " +
              escape(pat) + " = \"" +
              escape(saw) + "\"");
        // We should be able to round-trip the formatted string =>
        // number => string (but not the other way around: number
        // => string => number2, might have number2 != number):
        if (rt) {
            Formattable n2;
            fmt.parse(exp, n2, status);
            if (U_FAILURE(status)) {
                errln(UnicodeString("FAIL: Parse failed for \"") + exp + "\" - " + u_errorName(status));
                return;
            }
            UnicodeString saw2;
            fmt.format(n2, saw2, pos, status);
            CHECK(status, "NumberFormat::format");
            if (saw2 != exp) {
                errln((UnicodeString)"FAIL \"" + exp + "\" => " + toString(n2) +
                      " => \"" + saw2 + "\"");
            }
        }
    } else {
        dataerrln(UnicodeString("FAIL ") + toString(n) + " x " +
              escape(pat) + " = \"" +
              escape(saw) + "\", expected \"" + exp + "\"");
    }
}

Project: icu
File: number_decimalquantity.cpp

uint64_t DecimalQuantity::getPositionFingerprint() const {
    uint64_t fingerprint = 0;
    fingerprint ^= lOptPos;
    fingerprint ^= (lReqPos << 16);
    fingerprint ^= (static_cast<uint64_t>(rReqPos) << 32);
    fingerprint ^= (static_cast<uint64_t>(rOptPos) << 48);
    return fingerprint;
}

Project: icu
File: number_decimalquantity.cpp

int32_t DecimalQuantity::getUpperDisplayMagnitude() const {
    // If this assertion fails, you need to call roundToInfinity() or some other rounding method.
    // See the comment in the header file explaining the "isApproximate" field.
    U_ASSERT(!isApproximate);

    int32_t magnitude = scale + precision;
    int32_t result = (lReqPos > magnitude) ? lReqPos : (lOptPos < magnitude) ? lOptPos : magnitude;
    return result - 1;
}

Project: icu
File: fmtable.cpp

Formattable::Formattable(const Formattable* arrayToCopy, int32_t count)
    :   UObject(), fType(kArray)
{
    init();
    fType = kArray;
    fValue.fArrayAndCount.fArray = createArrayCopy(arrayToCopy, count);
    fValue.fArrayAndCount.fCount = count;
}

Project: icu
File: fmtable.cpp

Formattable::setInt64(int64_t ll)
{
    dispose();
    fType = kInt64;
    fValue.fInt64 = ll;
}

Project: icu
File: number_decimalquantity.cpp

bool DecimalQuantity::operator==(const DecimalQuantity& other) const {
    bool basicEquals =
            scale == other.scale
            && precision == other.precision
            && flags == other.flags
            && lOptPos == other.lOptPos
            && lReqPos == other.lReqPos
            && rReqPos == other.rReqPos
            && rOptPos == other.rOptPos
            && isApproximate == other.isApproximate;
    if (!basicEquals) {
        return false;
    }

    if (precision == 0) {
        return true;
    } else if (isApproximate) {
        return origDouble == other.origDouble && origDelta == other.origDelta;
    } else {
        for (int m = getUpperDisplayMagnitude(); m >= getLowerDisplayMagnitude(); m--) {
            if (getDigit(m) != other.getDigit(m)) {
                return false;
            }
        }
        return true;
    }
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::TestSignificantDigits(void) {
  double input[] = {
        0, 0,
        0.1, -0.1,
        123, -123,
        12345, -12345,
        123.45, -123.45,
        123.44501, -123.44501,
        0.001234, -0.001234,
        0.00000000123, -0.00000000123,
        0.0000000000000000000123, -0.0000000000000000000123,
        1.2, -1.2,
        0.0000000012344501, -0.0000000012344501,
        123445.01, -123445.01,
        12344501000000000000000000000000000.0, -12344501000000000000000000000000000.0,
    };
    const char* expected[] = {
        "0.00", "0.00",
        "0.100", "-0.100",
        "123", "-123",
        "12345", "-12345",
        "123.45", "-123.45",
        "123.45", "-123.45",
        "0.001234", "-0.001234",
        "0.00000000123", "-0.00000000123",
        "0.0000000000000000000123", "-0.0000000000000000000123",
        "1.20", "-1.20",
        "0.0000000012345", "-0.0000000012345",
        "123450", "-123450",
        "12345000000000000000000000000000000", "-12345000000000000000000000000000000",
    };

    UErrorCode status = U_ZERO_ERROR;
    Locale locale("en_US");
    LocalPointer<DecimalFormat> numberFormat(static_cast<DecimalFormat*>(
            NumberFormat::createInstance(locale, status)));
    CHECK_DATA(status,"NumberFormat::createInstance")

    numberFormat->setSignificantDigitsUsed(TRUE);
    numberFormat->setMinimumSignificantDigits(3);
    numberFormat->setMaximumSignificantDigits(5);
    numberFormat->setGroupingUsed(false);

    UnicodeString result;
    UnicodeString expectedResult;
    for (unsigned int i = 0; i < UPRV_LENGTHOF(input); ++i) {
        numberFormat->format(input[i], result);
        UnicodeString expectedResult(expected[i]);
        if (result != expectedResult) {
          errln((UnicodeString)"Expected: '" + expectedResult + "' got '" + result);
        }
        result.remove();
    }

    // Test for ICU-20063
    {
        DecimalFormat df({"en-us", status}, status);
        df.setSignificantDigitsUsed(TRUE);
        expect(df, 9.87654321, u"9.87654");
        df.setMaximumSignificantDigits(3);
        expect(df, 9.87654321, u"9.88");
        // setSignificantDigitsUsed with maxSig only
        df.setSignificantDigitsUsed(TRUE);
        expect(df, 9.87654321, u"9.88");
        df.setMinimumSignificantDigits(2);
        expect(df, 9, u"9.0");
        // setSignificantDigitsUsed with both minSig and maxSig
        df.setSignificantDigitsUsed(TRUE);
        expect(df, 9, u"9.0");
        // setSignificantDigitsUsed to false: should revert to fraction rounding
        df.setSignificantDigitsUsed(FALSE);
        expect(df, 9.87654321, u"9.876543");
        expect(df, 9, u"9");
        df.setSignificantDigitsUsed(TRUE);
        df.setMinimumSignificantDigits(2);
        expect(df, 9.87654321, u"9.87654");
        expect(df, 9, u"9.0");
        // setSignificantDigitsUsed with minSig only
        df.setSignificantDigitsUsed(TRUE);
        expect(df, 9.87654321, u"9.87654");
        expect(df, 9, u"9.0");
    }
}

Project: icu
File: number_decimalquantity.cpp

DecimalQuantity &DecimalQuantity::setToDecNumber(StringPiece n, UErrorCode& status) {
    setBcdToZero();
    flags = 0;

    // Compute the decNumber representation
    DecNum decnum;
    decnum.setTo(n, status);

    _setToDecNum(decnum, status);
    return *this;
}

Project: icu
File: number_decimalquantity.cpp

UnicodeString DecimalQuantity::toScientificString() const {
    U_ASSERT(!isApproximate);
    UnicodeString result;
    if (isNegative()) {
        result.append(u'-');
    }
    if (precision == 0) {
        result.append(u"0E+0", -1);
        return result;
    }
    // NOTE: It is not safe to add to lOptPos (aka maxInt) or subtract from
    // rOptPos (aka -maxFrac) due to overflow.
    int32_t upperPos = std::min(precision + scale, lOptPos) - scale - 1;
    int32_t lowerPos = std::max(scale, rOptPos) - scale;
    int32_t p = upperPos;
    result.append(u'0' + getDigitPos(p));
    if ((--p) >= lowerPos) {
        result.append(u'.');
        for (; p >= lowerPos; p--) {
            result.append(u'0' + getDigitPos(p));
        }
    }
    result.append(u'E');
    int32_t _scale = upperPos + scale;
    if (_scale == INT32_MIN) {
        result.append({u"-2147483648", -1});
        return result;
    } else if (_scale < 0) {
        _scale *= -1;
        result.append(u'-');
    } else {
        result.append(u'+');
    }
    if (_scale == 0) {
        result.append(u'0');
    }
    int32_t insertIndex = result.length();
    while (_scale > 0) {
        std::div_t res = std::div(_scale, 10);
        result.insert(insertIndex, u'0' + res.rem);
        _scale = res.quot;
    }
    return result;
}

Project: icu
File: fmtable.cpp

CharString *Formattable::internalGetCharString(UErrorCode &status) {
    if(fDecimalStr == NULL) {
      if (fDecimalQuantity == NULL) {
        // No decimal number for the formattable yet.  Which means the value was
        // set directly by the user as an int, int64 or double.  If the value came
        // from parsing, or from the user setting a decimal number, fDecimalNum
        // would already be set.
        //
        LocalPointer<DecimalQuantity> dq(new DecimalQuantity(), status);
        if (U_FAILURE(status)) { return nullptr; }
        populateDecimalQuantity(*dq, status);
        if (U_FAILURE(status)) { return nullptr; }
        fDecimalQuantity = dq.orphan();
      }

      fDecimalStr = new CharString();
      if (fDecimalStr == NULL) {
        status = U_MEMORY_ALLOCATION_ERROR;
        return NULL;
      }
      // Older ICUs called uprv_decNumberToString here, which is not exactly the same as
      // DecimalQuantity::toScientificString(). The biggest difference is that uprv_decNumberToString does
      // not print scientific notation for magnitudes greater than -5 and smaller than some amount (+5?).
      if (fDecimalQuantity->isZero()) {
        fDecimalStr->append("0", -1, status);
      } else if (fDecimalQuantity->getMagnitude() != INT32_MIN && std::abs(fDecimalQuantity->getMagnitude()) < 5) {
        fDecimalStr->appendInvariantChars(fDecimalQuantity->toPlainString(), status);
      } else {
        fDecimalStr->appendInvariantChars(fDecimalQuantity->toScientificString(), status);
      }
    }
    return fDecimalStr;
}

Project: icu
File: numfmtst.cpp

void NumberFormatTest::Test13840_ParseLongStringCrash() {
    IcuTestErrorCode status(*this, "Test13840_ParseLongStringCrash");

    LocalPointer<NumberFormat> nf(NumberFormat::createInstance("en", status), status);
    if (status.errIfFailureAndReset()) { return; }

    Formattable result;
    static const char16_t* bigString =
        u"111111111111111111111111111111111111111111111111111111111111111111111"
        u"111111111111111111111111111111111111111111111111111111111111111111111"
        u"111111111111111111111111111111111111111111111111111111111111111111111"
        u"111111111111111111111111111111111111111111111111111111111111111111111"
        u"111111111111111111111111111111111111111111111111111111111111111111111"
        u"111111111111111111111111111111111111111111111111111111111111111111111";
    nf->parse(bigString, result, status);

    // Normalize the input string:
    CharString expectedChars;
    expectedChars.appendInvariantChars(bigString, status);
    DecimalQuantity expectedDQ;
    expectedDQ.setToDecNumber(expectedChars.toStringPiece(), status);
    UnicodeString expectedUString = expectedDQ.toScientificString();

    // Get the output string:
    StringPiece actualChars = result.getDecimalNumber(status);
    UnicodeString actualUString = UnicodeString(actualChars.data(), actualChars.length(), US_INV);

    assertEquals("Should round-trip without crashing", expectedUString, actualUString);
}

Project: icu
File: fmtable.cpp

ufmt_getObject(const UFormattable *fmt, UErrorCode *status) {
  const Formattable *obj = Formattable::fromUFormattable(fmt);

  const void *ret = obj->getObject();
  if( ret==NULL &&
      (obj->getType() != Formattable::kObject) &&
      U_SUCCESS( *status )) {
    *status = U_INVALID_FORMAT_ERROR;
  }
  return ret;
}

Project: icu
File: numfmtst.cpp

NumberFormatTest::TestRounding487(void)
{
    UErrorCode status = U_ZERO_ERROR;
    NumberFormat *nf = NumberFormat::createInstance(status);
    if (U_FAILURE(status)) {
        dataerrln("Error calling NumberFormat::createInstance()");
        return;
    }

    roundingTest(*nf, 0.00159999, 4, "0.0016");
    roundingTest(*nf, 0.00995, 4, "0.01");

    roundingTest(*nf, 12.3995, 3, "12.4");

    roundingTest(*nf, 12.4999, 0, "12");
    roundingTest(*nf, - 19.5, 0, "-20");
    delete nf;
    if (U_FAILURE(status)) errln((UnicodeString)"FAIL: Status " + (int32_t)status);
}