123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988 |
- // © 2016 and later: Unicode, Inc. and others.
- // License & terms of use: http://www.unicode.org/copyright.html
- /*
- *******************************************************************************
- * Copyright (C) 1996-2015, International Business Machines
- * Corporation and others. All Rights Reserved.
- *******************************************************************************
- * Modification History:
- *
- * Date Name Description
- * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
- *******************************************************************************
- */
- #include "unicode/utypes.h"
- #if !UCONFIG_NO_FORMATTING
- #include "unicode/unum.h"
- #include "unicode/uloc.h"
- #include "unicode/numfmt.h"
- #include "unicode/decimfmt.h"
- #include "unicode/rbnf.h"
- #include "unicode/compactdecimalformat.h"
- #include "unicode/ustring.h"
- #include "unicode/fmtable.h"
- #include "unicode/dcfmtsym.h"
- #include "unicode/curramt.h"
- #include "unicode/localpointer.h"
- #include "unicode/udisplaycontext.h"
- #include "uassert.h"
- #include "cpputils.h"
- #include "cstring.h"
- U_NAMESPACE_USE
- U_CAPI UNumberFormat* U_EXPORT2
- unum_open( UNumberFormatStyle style,
- const char16_t* pattern,
- int32_t patternLength,
- const char* locale,
- UParseError* parseErr,
- UErrorCode* status) {
- if(U_FAILURE(*status)) {
- return nullptr;
- }
- NumberFormat *retVal = nullptr;
- switch(style) {
- case UNUM_DECIMAL:
- case UNUM_CURRENCY:
- case UNUM_PERCENT:
- case UNUM_SCIENTIFIC:
- case UNUM_CURRENCY_ISO:
- case UNUM_CURRENCY_PLURAL:
- case UNUM_CURRENCY_ACCOUNTING:
- case UNUM_CASH_CURRENCY:
- case UNUM_CURRENCY_STANDARD:
- retVal = NumberFormat::createInstance(Locale(locale), style, *status);
- break;
- case UNUM_PATTERN_DECIMAL: {
- UParseError tErr;
- /* UnicodeString can handle the case when patternLength = -1. */
- const UnicodeString pat(pattern, patternLength);
- if(parseErr==nullptr){
- parseErr = &tErr;
- }
- DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status);
- if(syms == nullptr) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return nullptr;
- }
- if (U_FAILURE(*status)) {
- delete syms;
- return nullptr;
- }
- retVal = new DecimalFormat(pat, syms, *parseErr, *status);
- if(retVal == nullptr) {
- delete syms;
- }
- } break;
- #if U_HAVE_RBNF
- case UNUM_PATTERN_RULEBASED: {
- UParseError tErr;
- /* UnicodeString can handle the case when patternLength = -1. */
- const UnicodeString pat(pattern, patternLength);
-
- if(parseErr==nullptr){
- parseErr = &tErr;
- }
-
- retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status);
- } break;
- case UNUM_SPELLOUT:
- retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
- break;
- case UNUM_ORDINAL:
- retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
- break;
- case UNUM_DURATION:
- retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
- break;
- case UNUM_NUMBERING_SYSTEM: {
- // if the locale ID specifies a numbering system, go through NumberFormat::createInstance()
- // to handle it properly (we have to specify UNUM_DEFAULT to get it to handle the numbering
- // system, but we'll always get a RuleBasedNumberFormat back); otherwise, just go ahead and
- // create a RuleBasedNumberFormat ourselves
- UErrorCode localErr = U_ZERO_ERROR;
- Locale localeObj(locale);
- int32_t keywordLength = localeObj.getKeywordValue("numbers", nullptr, 0, localErr);
- if (keywordLength > 0) {
- retVal = NumberFormat::createInstance(localeObj, UNUM_DEFAULT, *status);
- } else {
- retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, localeObj, *status);
- }
- } break;
- #endif
- case UNUM_DECIMAL_COMPACT_SHORT:
- retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status);
- break;
- case UNUM_DECIMAL_COMPACT_LONG:
- retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status);
- break;
- default:
- *status = U_UNSUPPORTED_ERROR;
- return nullptr;
- }
- if(retVal == nullptr && U_SUCCESS(*status)) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- }
- if (U_FAILURE(*status) && retVal != nullptr) {
- delete retVal;
- retVal = nullptr;
- }
- return reinterpret_cast<UNumberFormat *>(retVal);
- }
- U_CAPI void U_EXPORT2
- unum_close(UNumberFormat* fmt)
- {
- delete (NumberFormat*) fmt;
- }
- U_CAPI UNumberFormat* U_EXPORT2
- unum_clone(const UNumberFormat *fmt,
- UErrorCode *status)
- {
- if(U_FAILURE(*status))
- return 0;
-
- Format *res = 0;
- const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
- const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
- if (df != nullptr) {
- res = df->clone();
- } else {
- const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
- U_ASSERT(rbnf != nullptr);
- res = rbnf->clone();
- }
- if(res == 0) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
-
- return (UNumberFormat*) res;
- }
- U_CAPI int32_t U_EXPORT2
- unum_format( const UNumberFormat* fmt,
- int32_t number,
- char16_t* result,
- int32_t resultLength,
- UFieldPosition *pos,
- UErrorCode* status)
- {
- return unum_formatInt64(fmt, number, result, resultLength, pos, status);
- }
- U_CAPI int32_t U_EXPORT2
- unum_formatInt64(const UNumberFormat* fmt,
- int64_t number,
- char16_t* result,
- int32_t resultLength,
- UFieldPosition *pos,
- UErrorCode* status)
- {
- if(U_FAILURE(*status))
- return -1;
-
- UnicodeString res;
- if(!(result==nullptr && resultLength==0)) {
- // nullptr destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- res.setTo(result, 0, resultLength);
- }
-
- FieldPosition fp;
-
- if(pos != 0)
- fp.setField(pos->field);
-
- ((const NumberFormat*)fmt)->format(number, res, fp, *status);
- if(pos != 0) {
- pos->beginIndex = fp.getBeginIndex();
- pos->endIndex = fp.getEndIndex();
- }
-
- return res.extract(result, resultLength, *status);
- }
- U_CAPI int32_t U_EXPORT2
- unum_formatDouble( const UNumberFormat* fmt,
- double number,
- char16_t* result,
- int32_t resultLength,
- UFieldPosition *pos, /* 0 if ignore */
- UErrorCode* status)
- {
-
- if(U_FAILURE(*status)) return -1;
- UnicodeString res;
- if(!(result==nullptr && resultLength==0)) {
- // nullptr destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- res.setTo(result, 0, resultLength);
- }
- FieldPosition fp;
-
- if(pos != 0)
- fp.setField(pos->field);
-
- ((const NumberFormat*)fmt)->format(number, res, fp, *status);
-
- if(pos != 0) {
- pos->beginIndex = fp.getBeginIndex();
- pos->endIndex = fp.getEndIndex();
- }
-
- return res.extract(result, resultLength, *status);
- }
- U_CAPI int32_t U_EXPORT2
- unum_formatDoubleForFields(const UNumberFormat* format,
- double number,
- char16_t* result,
- int32_t resultLength,
- UFieldPositionIterator* fpositer,
- UErrorCode* status)
- {
- if (U_FAILURE(*status))
- return -1;
- if (result == nullptr ? resultLength != 0 : resultLength < 0) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- return -1;
- }
- UnicodeString res;
- if (result != nullptr) {
- // nullptr destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- res.setTo(result, 0, resultLength);
- }
- ((const NumberFormat*)format)->format(number, res, (FieldPositionIterator*)fpositer, *status);
- return res.extract(result, resultLength, *status);
- }
- U_CAPI int32_t U_EXPORT2
- unum_formatDecimal(const UNumberFormat* fmt,
- const char * number,
- int32_t length,
- char16_t* result,
- int32_t resultLength,
- UFieldPosition *pos, /* 0 if ignore */
- UErrorCode* status) {
- if(U_FAILURE(*status)) {
- return -1;
- }
- if ((result == nullptr && resultLength != 0) || resultLength < 0) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- return -1;
- }
- FieldPosition fp;
- if(pos != 0) {
- fp.setField(pos->field);
- }
- if (length < 0) {
- length = static_cast<int32_t>(uprv_strlen(number));
- }
- StringPiece numSP(number, length);
- Formattable numFmtbl(numSP, *status);
- UnicodeString resultStr;
- if (resultLength > 0) {
- // Alias the destination buffer.
- resultStr.setTo(result, 0, resultLength);
- }
- ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status);
- if(pos != 0) {
- pos->beginIndex = fp.getBeginIndex();
- pos->endIndex = fp.getEndIndex();
- }
- return resultStr.extract(result, resultLength, *status);
- }
- U_CAPI int32_t U_EXPORT2
- unum_formatDoubleCurrency(const UNumberFormat* fmt,
- double number,
- char16_t* currency,
- char16_t* result,
- int32_t resultLength,
- UFieldPosition* pos, /* ignored if 0 */
- UErrorCode* status) {
- if (U_FAILURE(*status)) return -1;
- UnicodeString res;
- if (!(result==nullptr && resultLength==0)) {
- // nullptr destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- res.setTo(result, 0, resultLength);
- }
-
- FieldPosition fp;
- if (pos != 0) {
- fp.setField(pos->field);
- }
- CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status);
- // Check for null pointer.
- if (tempCurrAmnt == nullptr) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return -1;
- }
- Formattable n(tempCurrAmnt);
- ((const NumberFormat*)fmt)->format(n, res, fp, *status);
-
- if (pos != 0) {
- pos->beginIndex = fp.getBeginIndex();
- pos->endIndex = fp.getEndIndex();
- }
-
- return res.extract(result, resultLength, *status);
- }
- static void
- parseRes(Formattable& res,
- const UNumberFormat* fmt,
- const char16_t* text,
- int32_t textLength,
- int32_t *parsePos /* 0 = start */,
- UErrorCode *status)
- {
- if(U_FAILURE(*status))
- return;
-
- const UnicodeString src((UBool)(textLength == -1), text, textLength);
- ParsePosition pp;
-
- if(parsePos != 0)
- pp.setIndex(*parsePos);
-
- ((const NumberFormat*)fmt)->parse(src, res, pp);
-
- if(pp.getErrorIndex() != -1) {
- *status = U_PARSE_ERROR;
- if(parsePos != 0) {
- *parsePos = pp.getErrorIndex();
- }
- } else if(parsePos != 0) {
- *parsePos = pp.getIndex();
- }
- }
- U_CAPI int32_t U_EXPORT2
- unum_parse( const UNumberFormat* fmt,
- const char16_t* text,
- int32_t textLength,
- int32_t *parsePos /* 0 = start */,
- UErrorCode *status)
- {
- Formattable res;
- parseRes(res, fmt, text, textLength, parsePos, status);
- return res.getLong(*status);
- }
- U_CAPI int64_t U_EXPORT2
- unum_parseInt64( const UNumberFormat* fmt,
- const char16_t* text,
- int32_t textLength,
- int32_t *parsePos /* 0 = start */,
- UErrorCode *status)
- {
- Formattable res;
- parseRes(res, fmt, text, textLength, parsePos, status);
- return res.getInt64(*status);
- }
- U_CAPI double U_EXPORT2
- unum_parseDouble( const UNumberFormat* fmt,
- const char16_t* text,
- int32_t textLength,
- int32_t *parsePos /* 0 = start */,
- UErrorCode *status)
- {
- Formattable res;
- parseRes(res, fmt, text, textLength, parsePos, status);
- return res.getDouble(*status);
- }
- U_CAPI int32_t U_EXPORT2
- unum_parseDecimal(const UNumberFormat* fmt,
- const char16_t* text,
- int32_t textLength,
- int32_t *parsePos /* 0 = start */,
- char *outBuf,
- int32_t outBufLength,
- UErrorCode *status)
- {
- if (U_FAILURE(*status)) {
- return -1;
- }
- if ((outBuf == nullptr && outBufLength != 0) || outBufLength < 0) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- return -1;
- }
- Formattable res;
- parseRes(res, fmt, text, textLength, parsePos, status);
- StringPiece sp = res.getDecimalNumber(*status);
- if (U_FAILURE(*status)) {
- return -1;
- } else if (sp.size() > outBufLength) {
- *status = U_BUFFER_OVERFLOW_ERROR;
- } else if (sp.size() == outBufLength) {
- uprv_strncpy(outBuf, sp.data(), sp.size());
- *status = U_STRING_NOT_TERMINATED_WARNING;
- } else {
- U_ASSERT(outBufLength > 0);
- uprv_strcpy(outBuf, sp.data());
- }
- return sp.size();
- }
- U_CAPI double U_EXPORT2
- unum_parseDoubleCurrency(const UNumberFormat* fmt,
- const char16_t* text,
- int32_t textLength,
- int32_t* parsePos, /* 0 = start */
- char16_t* currency,
- UErrorCode* status) {
- double doubleVal = 0.0;
- currency[0] = 0;
- if (U_FAILURE(*status)) {
- return doubleVal;
- }
- const UnicodeString src((UBool)(textLength == -1), text, textLength);
- ParsePosition pp;
- if (parsePos != nullptr) {
- pp.setIndex(*parsePos);
- }
- *status = U_PARSE_ERROR; // assume failure, reset if succeed
- LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp));
- if (pp.getErrorIndex() != -1) {
- if (parsePos != nullptr) {
- *parsePos = pp.getErrorIndex();
- }
- } else {
- if (parsePos != nullptr) {
- *parsePos = pp.getIndex();
- }
- if (pp.getIndex() > 0) {
- *status = U_ZERO_ERROR;
- u_strcpy(currency, currAmt->getISOCurrency());
- doubleVal = currAmt->getNumber().getDouble(*status);
- }
- }
- return doubleVal;
- }
- U_CAPI const char* U_EXPORT2
- unum_getAvailable(int32_t index)
- {
- return uloc_getAvailable(index);
- }
- U_CAPI int32_t U_EXPORT2
- unum_countAvailable()
- {
- return uloc_countAvailable();
- }
- U_CAPI bool U_EXPORT2
- unum_hasAttribute(const UNumberFormat* fmt,
- UNumberFormatAttribute attr)
- {
- const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
- bool isDecimalFormat = dynamic_cast<const DecimalFormat*>(nf) != nullptr;
-
- switch (attr) {
- case UNUM_LENIENT_PARSE:
- case UNUM_MAX_INTEGER_DIGITS:
- case UNUM_MIN_INTEGER_DIGITS:
- case UNUM_INTEGER_DIGITS:
- case UNUM_MAX_FRACTION_DIGITS:
- case UNUM_MIN_FRACTION_DIGITS:
- case UNUM_FRACTION_DIGITS:
- case UNUM_ROUNDING_MODE:
- return true;
- default:
- return isDecimalFormat;
- }
- }
- U_CAPI int32_t U_EXPORT2
- unum_getAttribute(const UNumberFormat* fmt,
- UNumberFormatAttribute attr)
- {
- const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
- if (attr == UNUM_LENIENT_PARSE) {
- // Supported for all subclasses
- return nf->isLenient();
- }
- else if (attr == UNUM_MAX_INTEGER_DIGITS) {
- return nf->getMaximumIntegerDigits();
- }
- else if (attr == UNUM_MIN_INTEGER_DIGITS) {
- return nf->getMinimumIntegerDigits();
- }
- else if (attr == UNUM_INTEGER_DIGITS) {
- // TODO: what should this return?
- return nf->getMinimumIntegerDigits();
- }
- else if (attr == UNUM_MAX_FRACTION_DIGITS) {
- return nf->getMaximumFractionDigits();
- }
- else if (attr == UNUM_MIN_FRACTION_DIGITS) {
- return nf->getMinimumFractionDigits();
- }
- else if (attr == UNUM_FRACTION_DIGITS) {
- // TODO: what should this return?
- return nf->getMinimumFractionDigits();
- }
- else if (attr == UNUM_ROUNDING_MODE) {
- return nf->getRoundingMode();
- }
- // The remaining attributes are only supported for DecimalFormat
- const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
- if (df != nullptr) {
- UErrorCode ignoredStatus = U_ZERO_ERROR;
- return df->getAttribute(attr, ignoredStatus);
- }
- return -1;
- }
- U_CAPI void U_EXPORT2
- unum_setAttribute( UNumberFormat* fmt,
- UNumberFormatAttribute attr,
- int32_t newValue)
- {
- NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
- if (attr == UNUM_LENIENT_PARSE) {
- // Supported for all subclasses
- // keep this here as the class may not be a DecimalFormat
- return nf->setLenient(newValue != 0);
- }
- else if (attr == UNUM_MAX_INTEGER_DIGITS) {
- return nf->setMaximumIntegerDigits(newValue);
- }
- else if (attr == UNUM_MIN_INTEGER_DIGITS) {
- return nf->setMinimumIntegerDigits(newValue);
- }
- else if (attr == UNUM_INTEGER_DIGITS) {
- nf->setMinimumIntegerDigits(newValue);
- return nf->setMaximumIntegerDigits(newValue);
- }
- else if (attr == UNUM_MAX_FRACTION_DIGITS) {
- return nf->setMaximumFractionDigits(newValue);
- }
- else if (attr == UNUM_MIN_FRACTION_DIGITS) {
- return nf->setMinimumFractionDigits(newValue);
- }
- else if (attr == UNUM_FRACTION_DIGITS) {
- nf->setMinimumFractionDigits(newValue);
- return nf->setMaximumFractionDigits(newValue);
- }
- else if (attr == UNUM_ROUNDING_MODE) {
- return nf->setRoundingMode((NumberFormat::ERoundingMode)newValue);
- }
- // The remaining attributes are only supported for DecimalFormat
- DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
- if (df != nullptr) {
- UErrorCode ignoredStatus = U_ZERO_ERROR;
- df->setAttribute(attr, newValue, ignoredStatus);
- }
- }
- U_CAPI double U_EXPORT2
- unum_getDoubleAttribute(const UNumberFormat* fmt,
- UNumberFormatAttribute attr)
- {
- const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
- const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
- if (df != nullptr && attr == UNUM_ROUNDING_INCREMENT) {
- return df->getRoundingIncrement();
- } else {
- return -1.0;
- }
- }
- U_CAPI void U_EXPORT2
- unum_setDoubleAttribute( UNumberFormat* fmt,
- UNumberFormatAttribute attr,
- double newValue)
- {
- NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
- DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
- if (df != nullptr && attr == UNUM_ROUNDING_INCREMENT) {
- df->setRoundingIncrement(newValue);
- }
- }
- U_CAPI int32_t U_EXPORT2
- unum_getTextAttribute(const UNumberFormat* fmt,
- UNumberFormatTextAttribute tag,
- char16_t* result,
- int32_t resultLength,
- UErrorCode* status)
- {
- if(U_FAILURE(*status))
- return -1;
- UnicodeString res;
- if(!(result==nullptr && resultLength==0)) {
- // nullptr destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- res.setTo(result, 0, resultLength);
- }
- const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
- const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
- if (df != nullptr) {
- switch(tag) {
- case UNUM_POSITIVE_PREFIX:
- df->getPositivePrefix(res);
- break;
- case UNUM_POSITIVE_SUFFIX:
- df->getPositiveSuffix(res);
- break;
- case UNUM_NEGATIVE_PREFIX:
- df->getNegativePrefix(res);
- break;
- case UNUM_NEGATIVE_SUFFIX:
- df->getNegativeSuffix(res);
- break;
- case UNUM_PADDING_CHARACTER:
- res = df->getPadCharacterString();
- break;
- case UNUM_CURRENCY_CODE:
- res = UnicodeString(df->getCurrency());
- break;
- default:
- *status = U_UNSUPPORTED_ERROR;
- return -1;
- }
- } else {
- const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
- U_ASSERT(rbnf != nullptr);
- if (tag == UNUM_DEFAULT_RULESET) {
- res = rbnf->getDefaultRuleSetName();
- } else if (tag == UNUM_PUBLIC_RULESETS) {
- int32_t count = rbnf->getNumberOfRuleSetNames();
- for (int i = 0; i < count; ++i) {
- res += rbnf->getRuleSetName(i);
- res += (char16_t)0x003b; // semicolon
- }
- } else {
- *status = U_UNSUPPORTED_ERROR;
- return -1;
- }
- }
- return res.extract(result, resultLength, *status);
- }
- U_CAPI void U_EXPORT2
- unum_setTextAttribute( UNumberFormat* fmt,
- UNumberFormatTextAttribute tag,
- const char16_t* newValue,
- int32_t newValueLength,
- UErrorCode *status)
- {
- if(U_FAILURE(*status))
- return;
- UnicodeString val(newValue, newValueLength);
- NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
- DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
- if (df != nullptr) {
- switch(tag) {
- case UNUM_POSITIVE_PREFIX:
- df->setPositivePrefix(val);
- break;
-
- case UNUM_POSITIVE_SUFFIX:
- df->setPositiveSuffix(val);
- break;
-
- case UNUM_NEGATIVE_PREFIX:
- df->setNegativePrefix(val);
- break;
-
- case UNUM_NEGATIVE_SUFFIX:
- df->setNegativeSuffix(val);
- break;
-
- case UNUM_PADDING_CHARACTER:
- df->setPadCharacter(val);
- break;
-
- case UNUM_CURRENCY_CODE:
- df->setCurrency(val.getTerminatedBuffer(), *status);
- break;
-
- default:
- *status = U_UNSUPPORTED_ERROR;
- break;
- }
- } else {
- RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf);
- U_ASSERT(rbnf != nullptr);
- if (tag == UNUM_DEFAULT_RULESET) {
- rbnf->setDefaultRuleSet(val, *status);
- } else {
- *status = U_UNSUPPORTED_ERROR;
- }
- }
- }
- U_CAPI int32_t U_EXPORT2
- unum_toPattern( const UNumberFormat* fmt,
- UBool isPatternLocalized,
- char16_t* result,
- int32_t resultLength,
- UErrorCode* status)
- {
- if(U_FAILURE(*status))
- return -1;
-
- UnicodeString pat;
- if(!(result==nullptr && resultLength==0)) {
- // nullptr destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- pat.setTo(result, 0, resultLength);
- }
- const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
- const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
- if (df != nullptr) {
- if(isPatternLocalized)
- df->toLocalizedPattern(pat);
- else
- df->toPattern(pat);
- } else {
- const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
- U_ASSERT(rbnf != nullptr);
- pat = rbnf->getRules();
- }
- return pat.extract(result, resultLength, *status);
- }
- U_CAPI int32_t U_EXPORT2
- unum_getSymbol(const UNumberFormat *fmt,
- UNumberFormatSymbol symbol,
- char16_t *buffer,
- int32_t size,
- UErrorCode *status) UPRV_NO_SANITIZE_UNDEFINED {
- if(status==nullptr || U_FAILURE(*status)) {
- return 0;
- }
- if(fmt==nullptr || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
- *status=U_ILLEGAL_ARGUMENT_ERROR;
- return 0;
- }
- const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt);
- const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf);
- if (dcf == nullptr) {
- *status = U_UNSUPPORTED_ERROR;
- return 0;
- }
- return dcf->
- getDecimalFormatSymbols()->
- getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
- extract(buffer, size, *status);
- }
- U_CAPI void U_EXPORT2
- unum_setSymbol(UNumberFormat *fmt,
- UNumberFormatSymbol symbol,
- const char16_t *value,
- int32_t length,
- UErrorCode *status) UPRV_NO_SANITIZE_UNDEFINED {
- if(status==nullptr || U_FAILURE(*status)) {
- return;
- }
- if(fmt==nullptr || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==nullptr || length<-1) {
- *status=U_ILLEGAL_ARGUMENT_ERROR;
- return;
- }
- NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt);
- DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf);
- if (dcf == nullptr) {
- *status = U_UNSUPPORTED_ERROR;
- return;
- }
- DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols());
- symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
- UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */
- dcf->setDecimalFormatSymbols(symbols);
- }
- U_CAPI void U_EXPORT2
- unum_applyPattern( UNumberFormat *fmt,
- UBool localized,
- const char16_t *pattern,
- int32_t patternLength,
- UParseError *parseError,
- UErrorCode* status)
- {
- UErrorCode tStatus = U_ZERO_ERROR;
- UParseError tParseError;
-
- if(parseError == nullptr){
- parseError = &tParseError;
- }
-
- if(status==nullptr){
- status = &tStatus;
- }
-
- int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
- const UnicodeString pat((char16_t*)pattern, len, len);
- // Verify if the object passed is a DecimalFormat object
- NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
- DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
- if (df != nullptr) {
- if(localized) {
- df->applyLocalizedPattern(pat,*parseError, *status);
- } else {
- df->applyPattern(pat,*parseError, *status);
- }
- } else {
- *status = U_UNSUPPORTED_ERROR;
- return;
- }
- }
- U_CAPI const char* U_EXPORT2
- unum_getLocaleByType(const UNumberFormat *fmt,
- ULocDataLocaleType type,
- UErrorCode* status)
- {
- if (fmt == nullptr) {
- if (U_SUCCESS(*status)) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- }
- return nullptr;
- }
- return ((const Format*)fmt)->getLocaleID(type, *status);
- }
- U_CAPI void U_EXPORT2
- unum_setContext(UNumberFormat* fmt, UDisplayContext value, UErrorCode* status)
- {
- if (U_FAILURE(*status)) {
- return;
- }
- ((NumberFormat*)fmt)->setContext(value, *status);
- return;
- }
- U_CAPI UDisplayContext U_EXPORT2
- unum_getContext(const UNumberFormat *fmt, UDisplayContextType type, UErrorCode* status)
- {
- if (U_FAILURE(*status)) {
- return (UDisplayContext)0;
- }
- return ((const NumberFormat*)fmt)->getContext(type, *status);
- }
- U_CAPI UFormattable * U_EXPORT2
- unum_parseToUFormattable(const UNumberFormat* fmt,
- UFormattable *result,
- const char16_t* text,
- int32_t textLength,
- int32_t* parsePos, /* 0 = start */
- UErrorCode* status) {
- UFormattable *newFormattable = nullptr;
- if (U_FAILURE(*status)) return result;
- if (fmt == nullptr || (text==nullptr && textLength!=0)) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- return result;
- }
- if (result == nullptr) { // allocate if not allocated.
- newFormattable = result = ufmt_open(status);
- }
- parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status);
- if (U_FAILURE(*status) && newFormattable != nullptr) {
- ufmt_close(newFormattable);
- result = nullptr; // deallocate if there was a parse error
- }
- return result;
- }
- U_CAPI int32_t U_EXPORT2
- unum_formatUFormattable(const UNumberFormat* fmt,
- const UFormattable *number,
- char16_t *result,
- int32_t resultLength,
- UFieldPosition *pos, /* ignored if 0 */
- UErrorCode *status) {
- if (U_FAILURE(*status)) {
- return 0;
- }
- if (fmt == nullptr || number==nullptr ||
- (result==nullptr ? resultLength!=0 : resultLength<0)) {
- *status = U_ILLEGAL_ARGUMENT_ERROR;
- return 0;
- }
- UnicodeString res(result, 0, resultLength);
- FieldPosition fp;
- if(pos != 0)
- fp.setField(pos->field);
- ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status);
- if(pos != 0) {
- pos->beginIndex = fp.getBeginIndex();
- pos->endIndex = fp.getEndIndex();
- }
- return res.extract(result, resultLength, *status);
- }
- #endif /* #if !UCONFIG_NO_FORMATTING */
|