+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
-* Copyright (C) 1996-2003, International Business Machines
+* Copyright (C) 1996-2015, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
* Modification History:
#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"
-U_NAMESPACE_USE
-/*
-U_CAPI UNumberFormat*
-unum_open( UNumberFormatStyle style,
- const char* locale,
- UErrorCode* status)
-{
- if(U_FAILURE(*status))
- return 0;
- UNumberFormat *retVal = 0;
-
- switch(style) {
- case UNUM_DECIMAL:
- if(locale == 0)
- retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
- else
- retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
- *status);
- break;
-
- case UNUM_CURRENCY:
- if(locale == 0)
- retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
- else
- retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
- *status);
- break;
-
- case UNUM_PERCENT:
- if(locale == 0)
- retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
- else
- retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
- *status);
- break;
-
- case UNUM_SPELLOUT:
- // Todo: TBD: Add spellout support
- //retVal = (UNumberFormat*)new NumberSpelloutFormat();
- //break;
- *status = U_UNSUPPORTED_ERROR;
- return 0;
-
- default:
- *status = U_UNSUPPORTED_ERROR;
- return 0;
- }
+#include "cstring.h"
- if(retVal == 0) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
- return retVal;
-}
-
-U_CAPI UNumberFormat*
-unum_openPattern( const UChar* pattern,
- int32_t patternLength,
- const char* locale,
- UErrorCode* status)
-{
- UParseError parseError;
- return unum_openPatternWithError( pattern,patternLength,locale,&parseError,status);
-}*/
+U_NAMESPACE_USE
U_CAPI UNumberFormat* U_EXPORT2
int32_t patternLength,
const char* locale,
UParseError* parseErr,
- UErrorCode* status)
-{
+ UErrorCode* status) {
+ if(U_FAILURE(*status)) {
+ return NULL;
+ }
- if(U_FAILURE(*status))
- {
- return 0;
- }
- if(style!=UNUM_IGNORE){
- UNumberFormat *retVal = 0;
-
- switch(style) {
- case UNUM_DECIMAL:
- if(locale == 0)
- retVal = (UNumberFormat*)NumberFormat::createInstance(*status);
- else
- retVal = (UNumberFormat*)NumberFormat::createInstance(Locale(locale),
- *status);
+ NumberFormat *retVal = NULL;
+
+ 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_CURRENCY:
- if(locale == 0)
- retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(*status);
- else
- retVal = (UNumberFormat*)NumberFormat::createCurrencyInstance(Locale(locale),
- *status);
+ case UNUM_PATTERN_DECIMAL: {
+ UParseError tErr;
+ /* UnicodeString can handle the case when patternLength = -1. */
+ const UnicodeString pat(pattern, patternLength);
+
+ if(parseErr==NULL){
+ parseErr = &tErr;
+ }
+
+ DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status);
+ if(syms == NULL) {
+ *status = U_MEMORY_ALLOCATION_ERROR;
+ return NULL;
+ }
+ if (U_FAILURE(*status)) {
+ delete syms;
+ return NULL;
+ }
+
+ retVal = new DecimalFormat(pat, syms, *parseErr, *status);
+ if(retVal == NULL) {
+ 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==NULL){
+ 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_PERCENT:
- if(locale == 0)
- retVal = (UNumberFormat*)NumberFormat::createPercentInstance(*status);
- else
- retVal = (UNumberFormat*)NumberFormat::createPercentInstance(Locale(locale),
- *status);
+ case UNUM_ORDINAL:
+ retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status);
break;
- case UNUM_SCIENTIFIC:
- if(locale == 0)
- retVal = (UNumberFormat*)NumberFormat::createScientificInstance(*status);
- else
- retVal = (UNumberFormat*)NumberFormat::createScientificInstance(Locale(locale),
- *status);
+ case UNUM_DURATION:
+ retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status);
break;
- case UNUM_SPELLOUT:
-#if U_HAVE_RBNF
- return (UNumberFormat*)new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status);
-#else
- // fall through
+ case UNUM_NUMBERING_SYSTEM:
+ retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status);
+ break;
#endif
- default:
- *status = U_UNSUPPORTED_ERROR;
- return 0;
- }
- if(retVal == 0) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
+ case UNUM_DECIMAL_COMPACT_SHORT:
+ retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status);
+ break;
- return retVal;
- }else{
- /* we don't support RBNF patterns yet */
- UParseError tErr;
- int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
- const UnicodeString pat((UChar*)pattern, len, len);
- DecimalFormatSymbols *syms = 0;
-
- if(parseErr==NULL){
- parseErr = &tErr;
- }
-
- if(locale == 0)
- syms = new DecimalFormatSymbols(*status);
- else
- syms = new DecimalFormatSymbols(Locale(locale),
- *status);
-
- if(syms == 0) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
+ case UNUM_DECIMAL_COMPACT_LONG:
+ retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status);
+ break;
+
+ default:
+ *status = U_UNSUPPORTED_ERROR;
+ return NULL;
+ }
- DecimalFormat *fmt = 0;
- fmt = new DecimalFormat(pat, syms, *parseErr, *status);
- if(fmt == 0) {
+ if(retVal == NULL && U_SUCCESS(*status)) {
*status = U_MEMORY_ALLOCATION_ERROR;
- delete syms;
- return 0;
- }
+ }
- return (UNumberFormat*) fmt;
- }
+ return reinterpret_cast<UNumberFormat *>(retVal);
}
U_CAPI void U_EXPORT2
unum_close(UNumberFormat* fmt)
{
-
- delete (NumberFormat*) fmt;
+ delete (NumberFormat*) fmt;
}
U_CAPI UNumberFormat* U_EXPORT2
unum_clone(const UNumberFormat *fmt,
UErrorCode *status)
{
-
- if(U_FAILURE(*status)) return 0;
-
- Format *res = ((DecimalFormat*)fmt)->clone();
-
- if(res == 0) {
- *status = U_MEMORY_ALLOCATION_ERROR;
- return 0;
- }
+ 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 != NULL) {
+ res = df->clone();
+ } else {
+ const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
+ U_ASSERT(rbnf != NULL);
+ res = rbnf->clone();
+ }
- return (UNumberFormat*) res;
+ 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,
+ int32_t number,
UChar* result,
- int32_t resultLength,
+ int32_t resultLength,
UFieldPosition *pos,
- UErrorCode* status)
+ UErrorCode* status)
{
-
- if(U_FAILURE(*status)) return -1;
+ return unum_formatInt64(fmt, number, result, resultLength, pos, status);
+}
- UnicodeString res;
- if(!(result==NULL && resultLength==0)) {
- // NULL destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- res.setTo(result, 0, resultLength);
- }
+U_CAPI int32_t U_EXPORT2
+unum_formatInt64(const UNumberFormat* fmt,
+ int64_t number,
+ UChar* result,
+ int32_t resultLength,
+ UFieldPosition *pos,
+ UErrorCode* status)
+{
+ if(U_FAILURE(*status))
+ return -1;
+
+ UnicodeString res;
+ if(!(result==NULL && resultLength==0)) {
+ // NULL 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 CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt);
+ if (cdf != NULL) {
+ cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !!
+ } else {
+ ((const NumberFormat*)fmt)->format(number, res, fp, *status);
+ }
- FieldPosition fp;
-
- if(pos != 0)
- fp.setField(pos->field);
-
- ((NumberFormat*)fmt)->format(number, res, fp);
-
- if(pos != 0) {
- pos->beginIndex = fp.getBeginIndex();
- pos->endIndex = fp.getEndIndex();
- }
-
- return res.extract(result, resultLength, *status);
+ if(pos != 0) {
+ pos->beginIndex = fp.getBeginIndex();
+ pos->endIndex = fp.getEndIndex();
+ }
+
+ return res.extract(result, resultLength, *status);
}
U_CAPI int32_t U_EXPORT2
if(pos != 0)
fp.setField(pos->field);
- ((NumberFormat*)fmt)->format(number, res, fp);
+ const CompactDecimalFormat* cdf = dynamic_cast<const CompactDecimalFormat*>((const NumberFormat*)fmt);
+ if (cdf != NULL) {
+ cdf->format(number, res, fp); // CompactDecimalFormat does not override the version with UErrorCode& !!
+ } else {
+ ((const NumberFormat*)fmt)->format(number, res, fp, *status);
+ }
if(pos != 0) {
pos->beginIndex = fp.getBeginIndex();
}
U_CAPI int32_t U_EXPORT2
-unum_parse( const UNumberFormat* fmt,
- const UChar* text,
- int32_t textLength,
- int32_t *parsePos /* 0 = start */,
- UErrorCode *status)
+unum_formatDoubleForFields(const UNumberFormat* format,
+ double number,
+ UChar* result,
+ int32_t resultLength,
+ UFieldPositionIterator* fpositer,
+ UErrorCode* status)
{
-
- if(U_FAILURE(*status)) return 0;
+ if (U_FAILURE(*status))
+ return -1;
- int32_t len = (textLength == -1 ? u_strlen(text) : textLength);
- const UnicodeString src((UChar*)text, len, len);
- ParsePosition pp;
- Formattable res;
+ if (result == NULL ? resultLength != 0 : resultLength < 0) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return -1;
+ }
- if(parsePos != 0)
- pp.setIndex(*parsePos);
+ UnicodeString res;
+ if (result != NULL) {
+ // NULL 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);
- ((NumberFormat*)fmt)->parse(src, res, pp);
+ return res.extract(result, resultLength, *status);
+}
+
+U_CAPI int32_t U_EXPORT2
+unum_formatDecimal(const UNumberFormat* fmt,
+ const char * number,
+ int32_t length,
+ UChar* result,
+ int32_t resultLength,
+ UFieldPosition *pos, /* 0 if ignore */
+ UErrorCode* status) {
- if(parsePos != 0) {
- if(pp.getErrorIndex() == -1)
- *parsePos = pp.getIndex();
- else {
- *parsePos = pp.getErrorIndex();
- *status = U_PARSE_ERROR;
+ if(U_FAILURE(*status)) {
+ return -1;
}
- }
+ if ((result == NULL && 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);
- /* return the actual type of the result, cast to a long */
- return (res.getType() == Formattable::kLong)
- ? res.getLong()
- : (int32_t) res.getDouble();
+ 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,
+ UChar* currency,
+ UChar* result,
+ int32_t resultLength,
+ UFieldPosition* pos, /* ignored if 0 */
+ UErrorCode* status) {
+ if (U_FAILURE(*status)) return -1;
+
+ UnicodeString res;
+ if (!(result==NULL && resultLength==0)) {
+ // NULL 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 == NULL) {
+ *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 UChar* 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 UChar* 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 UChar* 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
int32_t *parsePos /* 0 = start */,
UErrorCode *status)
{
-
- if(U_FAILURE(*status))
- return 0;
-
- int32_t len = (textLength < 0 ? u_strlen(text) : textLength);
- const UnicodeString src((UChar*)text, len, len);
- ParsePosition pp;
- Formattable res;
-
- if(parsePos != 0)
- pp.setIndex(*parsePos);
+ Formattable res;
+ parseRes(res, fmt, text, textLength, parsePos, status);
+ return res.getDouble(*status);
+}
- ((NumberFormat*)fmt)->parse(src, res, pp);
+U_CAPI int32_t U_EXPORT2
+unum_parseDecimal(const UNumberFormat* fmt,
+ const UChar* text,
+ int32_t textLength,
+ int32_t *parsePos /* 0 = start */,
+ char *outBuf,
+ int32_t outBufLength,
+ UErrorCode *status)
+{
+ if (U_FAILURE(*status)) {
+ return -1;
+ }
+ if ((outBuf == NULL && 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();
+}
- if(parsePos != 0) {
- if(pp.getErrorIndex() == -1)
- *parsePos = pp.getIndex();
- else {
- *parsePos = pp.getErrorIndex();
- *status = U_PARSE_ERROR;
+U_CAPI double U_EXPORT2
+unum_parseDoubleCurrency(const UNumberFormat* fmt,
+ const UChar* text,
+ int32_t textLength,
+ int32_t* parsePos, /* 0 = start */
+ UChar* currency,
+ UErrorCode* status) {
+ double doubleVal = 0.0;
+ currency[0] = 0;
+ if (U_FAILURE(*status)) {
+ return doubleVal;
}
- }
-
- /* return the actual type of the result, cast to a double */
- return (res.getType() == Formattable::kDouble)
- ? res.getDouble()
- : (double) res.getLong();
+ const UnicodeString src((UBool)(textLength == -1), text, textLength);
+ ParsePosition pp;
+ if (parsePos != NULL) {
+ 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 != NULL) {
+ *parsePos = pp.getErrorIndex();
+ }
+ } else {
+ if (parsePos != NULL) {
+ *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);
+ return uloc_getAvailable(index);
}
U_CAPI int32_t U_EXPORT2
unum_countAvailable()
{
-
- return uloc_countAvailable();
+ return uloc_countAvailable();
}
U_CAPI int32_t U_EXPORT2
unum_getAttribute(const UNumberFormat* fmt,
UNumberFormatAttribute attr)
{
-
- switch(attr) {
- case UNUM_PARSE_INT_ONLY:
- return ((NumberFormat*)fmt)->isParseIntegerOnly();
-
- case UNUM_GROUPING_USED:
- return ((NumberFormat*)fmt)->isGroupingUsed();
-
- case UNUM_DECIMAL_ALWAYS_SHOWN:
- return ((DecimalFormat*)fmt)->isDecimalSeparatorAlwaysShown();
-
- case UNUM_MAX_INTEGER_DIGITS:
- return ((NumberFormat*)fmt)->getMaximumIntegerDigits();
-
- case UNUM_MIN_INTEGER_DIGITS:
- return ((NumberFormat*)fmt)->getMinimumIntegerDigits();
-
- case UNUM_INTEGER_DIGITS:
- // TBD: what should this return?
- return ((NumberFormat*)fmt)->getMinimumIntegerDigits();
-
- case UNUM_MAX_FRACTION_DIGITS:
- return ((NumberFormat*)fmt)->getMaximumFractionDigits();
-
- case UNUM_MIN_FRACTION_DIGITS:
- return ((NumberFormat*)fmt)->getMinimumFractionDigits();
-
- case UNUM_FRACTION_DIGITS:
- // TBD: what should this return?
- return ((NumberFormat*)fmt)->getMinimumFractionDigits();
-
- case UNUM_MULTIPLIER:
- return ((DecimalFormat*)fmt)->getMultiplier();
-
- case UNUM_GROUPING_SIZE:
- return ((DecimalFormat*)fmt)->getGroupingSize();
-
- case UNUM_ROUNDING_MODE:
- return ((DecimalFormat*)fmt)->getRoundingMode();
-
- case UNUM_FORMAT_WIDTH:
- return ((DecimalFormat*)fmt)->getFormatWidth();
+ 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 position at which padding will take place. */
- case UNUM_PADDING_POSITION:
- return ((DecimalFormat*)fmt)->getPadPosition();
+ // The remaining attributes are only supported for DecimalFormat
+ const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+ if (df != NULL) {
+ UErrorCode ignoredStatus = U_ZERO_ERROR;
+ return df->getAttribute(attr, ignoredStatus);
+ }
- default:
- break;
- }
- return -1;
+ return -1;
}
U_CAPI void U_EXPORT2
UNumberFormatAttribute attr,
int32_t newValue)
{
-
- switch(attr) {
- case UNUM_PARSE_INT_ONLY:
- ((NumberFormat*)fmt)->setParseIntegerOnly((UBool)newValue);
- break;
-
- case UNUM_GROUPING_USED:
- ((NumberFormat*)fmt)->setGroupingUsed((UBool)newValue);
- break;
-
- case UNUM_DECIMAL_ALWAYS_SHOWN:
- ((DecimalFormat*)fmt)->setDecimalSeparatorAlwaysShown((UBool)newValue);
- break;
-
- case UNUM_MAX_INTEGER_DIGITS:
- ((NumberFormat*)fmt)->setMaximumIntegerDigits(newValue);
- break;
-
- case UNUM_MIN_INTEGER_DIGITS:
- ((NumberFormat*)fmt)->setMinimumIntegerDigits(newValue);
- break;
-
- case UNUM_INTEGER_DIGITS:
- ((NumberFormat*)fmt)->setMinimumIntegerDigits(newValue);
- ((NumberFormat*)fmt)->setMaximumIntegerDigits(newValue);
- break;
-
- case UNUM_MAX_FRACTION_DIGITS:
- ((NumberFormat*)fmt)->setMaximumFractionDigits(newValue);
- break;
-
- case UNUM_MIN_FRACTION_DIGITS:
- ((NumberFormat*)fmt)->setMinimumFractionDigits(newValue);
- break;
-
- case UNUM_FRACTION_DIGITS:
- ((NumberFormat*)fmt)->setMinimumFractionDigits(newValue);
- ((NumberFormat*)fmt)->setMaximumFractionDigits(newValue);
- break;
-
- case UNUM_MULTIPLIER:
- ((DecimalFormat*)fmt)->setMultiplier(newValue);
- break;
-
- case UNUM_GROUPING_SIZE:
- ((DecimalFormat*)fmt)->setGroupingSize(newValue);
- break;
-
- case UNUM_ROUNDING_MODE:
- ((DecimalFormat*)fmt)->setRoundingMode((DecimalFormat::ERoundingMode)newValue);
- break;
-
- case UNUM_FORMAT_WIDTH:
- ((DecimalFormat*)fmt)->setFormatWidth(newValue);
- break;
-
- /** The position at which padding will take place. */
- case UNUM_PADDING_POSITION:
- ((DecimalFormat*)fmt)->setPadPosition((DecimalFormat::EPadPosition)newValue);
- break;
-
- case UNUM_SECONDARY_GROUPING_SIZE:
- ((DecimalFormat*)fmt)->setSecondaryGroupingSize(newValue);
- break;
-
- default:
- /* Shouldn't get here anyway */
- break;
- }
+ 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 != NULL) {
+ UErrorCode ignoredStatus = U_ZERO_ERROR;
+ df->setAttribute(attr, newValue, ignoredStatus);
+ }
}
U_CAPI double U_EXPORT2
unum_getDoubleAttribute(const UNumberFormat* fmt,
UNumberFormatAttribute attr)
{
-
- if (attr == UNUM_ROUNDING_INCREMENT) {
- return ((DecimalFormat*)fmt)->getRoundingIncrement();
- } else {
- return -1.0;
- }
+ const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+ const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+ if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {
+ return df->getRoundingIncrement();
+ } else {
+ return -1.0;
+ }
}
U_CAPI void U_EXPORT2
UNumberFormatAttribute attr,
double newValue)
{
-
- if (attr == UNUM_ROUNDING_INCREMENT) {
- ((DecimalFormat*)fmt)->setRoundingIncrement(newValue);
- }
+ NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
+ DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
+ if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) {
+ df->setRoundingIncrement(newValue);
+ }
}
U_CAPI int32_t U_EXPORT2
int32_t resultLength,
UErrorCode* status)
{
-
- if(U_FAILURE(*status))
- return -1;
-
- UnicodeString res;
- if(!(result==NULL && resultLength==0)) {
- // NULL destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- res.setTo(result, 0, resultLength);
- }
-
- switch(tag) {
- case UNUM_POSITIVE_PREFIX:
- ((DecimalFormat*)fmt)->getPositivePrefix(res);
- break;
-
- case UNUM_POSITIVE_SUFFIX:
- ((DecimalFormat*)fmt)->getPositiveSuffix(res);
- break;
-
- case UNUM_NEGATIVE_PREFIX:
- ((DecimalFormat*)fmt)->getNegativePrefix(res);
- break;
-
- case UNUM_NEGATIVE_SUFFIX:
- ((DecimalFormat*)fmt)->getNegativeSuffix(res);
- break;
-
- case UNUM_PADDING_CHARACTER:
- res = ((DecimalFormat*)fmt)->getPadCharacterString();
- break;
-
- case UNUM_CURRENCY_CODE:
- res = UnicodeString(((DecimalFormat*)fmt)->getCurrency());
- break;
+ if(U_FAILURE(*status))
+ return -1;
+
+ UnicodeString res;
+ if(!(result==NULL && resultLength==0)) {
+ // NULL destination for pure preflighting: empty dummy string
+ // otherwise, alias the destination buffer
+ res.setTo(result, 0, resultLength);
+ }
- default:
- *status = U_UNSUPPORTED_ERROR;
- return -1;
- }
+ const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+ const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+ if (df != NULL) {
+ 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 != NULL);
+ 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 += (UChar)0x003b; // semicolon
+ }
+ } else {
+ *status = U_UNSUPPORTED_ERROR;
+ return -1;
+ }
+ }
- return res.extract(result, resultLength, *status);
+ return res.extract(result, resultLength, *status);
}
U_CAPI void U_EXPORT2
int32_t newValueLength,
UErrorCode *status)
{
-
- if(U_FAILURE(*status)) return;
-
- int32_t len = (newValueLength == -1 ? u_strlen(newValue) : newValueLength);
- const UnicodeString val((UChar*)newValue, len, len);
-
- switch(tag) {
- case UNUM_POSITIVE_PREFIX:
- ((DecimalFormat*)fmt)->setPositivePrefix(val);
- break;
-
- case UNUM_POSITIVE_SUFFIX:
- ((DecimalFormat*)fmt)->setPositiveSuffix(val);
- break;
-
- case UNUM_NEGATIVE_PREFIX:
- ((DecimalFormat*)fmt)->setNegativePrefix(val);
- break;
-
- case UNUM_NEGATIVE_SUFFIX:
- ((DecimalFormat*)fmt)->setNegativeSuffix(val);
- break;
-
- case UNUM_PADDING_CHARACTER:
- ((DecimalFormat*)fmt)->setPadCharacter(*newValue);
- break;
-
- case UNUM_CURRENCY_CODE:
- ((DecimalFormat*)fmt)->setCurrency(newValue);
- break;
-
- default:
- *status = U_UNSUPPORTED_ERROR;
- break;
- }
+ if(U_FAILURE(*status))
+ return;
+
+ UnicodeString val(newValue, newValueLength);
+ NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt);
+ DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf);
+ if (df != NULL) {
+ 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 != NULL);
+ if (tag == UNUM_DEFAULT_RULESET) {
+ rbnf->setDefaultRuleSet(val, *status);
+ } else {
+ *status = U_UNSUPPORTED_ERROR;
+ }
+ }
}
U_CAPI int32_t U_EXPORT2
int32_t resultLength,
UErrorCode* status)
{
-
- if(U_FAILURE(*status)) return -1;
-
- UnicodeString pat;
- if(!(result==NULL && resultLength==0)) {
- // NULL destination for pure preflighting: empty dummy string
- // otherwise, alias the destination buffer
- pat.setTo(result, 0, resultLength);
- }
-
- if(isPatternLocalized)
- ((DecimalFormat*)fmt)->toLocalizedPattern(pat);
- else
- ((DecimalFormat*)fmt)->toPattern(pat);
+ if(U_FAILURE(*status))
+ return -1;
+
+ UnicodeString pat;
+ if(!(result==NULL && resultLength==0)) {
+ // NULL destination for pure preflighting: empty dummy string
+ // otherwise, alias the destination buffer
+ pat.setTo(result, 0, resultLength);
+ }
- return pat.extract(result, resultLength, *status);
+ const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt);
+ const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf);
+ if (df != NULL) {
+ if(isPatternLocalized)
+ df->toLocalizedPattern(pat);
+ else
+ df->toPattern(pat);
+ } else {
+ const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf);
+ U_ASSERT(rbnf != NULL);
+ pat = rbnf->getRules();
+ }
+ return pat.extract(result, resultLength, *status);
}
U_CAPI int32_t U_EXPORT2
-unum_getSymbol(UNumberFormat *fmt,
+unum_getSymbol(const UNumberFormat *fmt,
UNumberFormatSymbol symbol,
UChar *buffer,
int32_t size,
- UErrorCode *status) {
-
- if(status==NULL || U_FAILURE(*status)) {
- return 0;
- }
-
- if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT) {
- *status=U_ILLEGAL_ARGUMENT_ERROR;
- return 0;
- }
+ UErrorCode *status)
+{
+ if(status==NULL || U_FAILURE(*status)) {
+ return 0;
+ }
+ if(fmt==NULL || 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 == NULL) {
+ *status = U_UNSUPPORTED_ERROR;
+ return 0;
+ }
- return
- ((const DecimalFormat *)fmt)->
+ return dcf->
getDecimalFormatSymbols()->
getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol).
extract(buffer, size, *status);
UNumberFormatSymbol symbol,
const UChar *value,
int32_t length,
- UErrorCode *status) {
-
- if(status==NULL || U_FAILURE(*status)) {
- return;
- }
-
- if(fmt==NULL || (uint16_t)symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
- *status=U_ILLEGAL_ARGUMENT_ERROR;
- return;
- }
-
- DecimalFormatSymbols symbols(*((DecimalFormat *)fmt)->getDecimalFormatSymbols());
- symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol,
- length>=0 ? UnicodeString(value, length) : UnicodeString(value));
- ((DecimalFormat *)fmt)->setDecimalFormatSymbols(symbols);
-}
-
-/*
-U_CAPI void
-unum_applyPattern( UNumberFormat *format,
- UBool localized,
- const UChar *pattern,
- int32_t patternLength
- )
+ UErrorCode *status)
{
- UErrorCode status = U_ZERO_ERROR;
- UParseError parseError;
- unum_applyPatternWithError(format,localized,pattern,patternLength,&parseError,&status);
+ if(status==NULL || U_FAILURE(*status)) {
+ return;
+ }
+ if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) {
+ *status=U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+ NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt);
+ DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf);
+ if (dcf == NULL) {
+ *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 *format,
+unum_applyPattern( UNumberFormat *fmt,
UBool localized,
const UChar *pattern,
int32_t patternLength,
UParseError *parseError,
UErrorCode* status)
{
-
- UErrorCode tStatus = U_ZERO_ERROR;
- UParseError tParseError;
-
- if(parseError == NULL){
- parseError = &tParseError;
+ UErrorCode tStatus = U_ZERO_ERROR;
+ UParseError tParseError;
+
+ if(parseError == NULL){
+ parseError = &tParseError;
+ }
+
+ if(status==NULL){
+ status = &tStatus;
+ }
+
+ int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
+ const UnicodeString pat((UChar*)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 != NULL) {
+ 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 == NULL) {
+ if (U_SUCCESS(*status)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ }
+ return NULL;
+ }
+ 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_INTERNAL UFormattable * U_EXPORT2
+unum_parseToUFormattable(const UNumberFormat* fmt,
+ UFormattable *result,
+ const UChar* text,
+ int32_t textLength,
+ int32_t* parsePos, /* 0 = start */
+ UErrorCode* status) {
+ UFormattable *newFormattable = NULL;
+ if (U_FAILURE(*status)) return result;
+ if (fmt == NULL || (text==NULL && textLength!=0)) {
+ *status = U_ILLEGAL_ARGUMENT_ERROR;
+ return result;
}
-
- if(status==NULL){
- status = &tStatus;
+ if (result == NULL) { // allocate if not allocated.
+ newFormattable = result = ufmt_open(status);
}
+ parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status);
+ if (U_FAILURE(*status) && newFormattable != NULL) {
+ ufmt_close(newFormattable);
+ result = NULL; // deallocate if there was a parse error
+ }
+ return result;
+}
- int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength);
- const UnicodeString pat((UChar*)pattern, len, len);
-
- // Verify if the object passed is a DecimalFormat object
- if(((NumberFormat*)format)->getDynamicClassID()!= DecimalFormat::getStaticClassID()){
+U_INTERNAL int32_t U_EXPORT2
+unum_formatUFormattable(const UNumberFormat* fmt,
+ const UFormattable *number,
+ UChar *result,
+ int32_t resultLength,
+ UFieldPosition *pos, /* ignored if 0 */
+ UErrorCode *status) {
+ if (U_FAILURE(*status)) {
+ return 0;
+ }
+ if (fmt == NULL || number==NULL ||
+ (result==NULL ? resultLength!=0 : resultLength<0)) {
*status = U_ILLEGAL_ARGUMENT_ERROR;
- return;
- }
-
- if(localized)
- ((DecimalFormat*)format)->applyLocalizedPattern(pat,*parseError, *status);
- else
- ((DecimalFormat*)format)->applyPattern(pat,*parseError, *status);
+ 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 */