michael@0: /* michael@0: ******************************************************************************* michael@0: * Copyright (C) 1996-2013, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ******************************************************************************* michael@0: * Modification History: michael@0: * michael@0: * Date Name Description michael@0: * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes michael@0: ******************************************************************************* michael@0: */ michael@0: michael@0: #include "unicode/utypes.h" michael@0: michael@0: #if !UCONFIG_NO_FORMATTING michael@0: michael@0: #include "unicode/unum.h" michael@0: michael@0: #include "unicode/uloc.h" michael@0: #include "unicode/numfmt.h" michael@0: #include "unicode/decimfmt.h" michael@0: #include "unicode/rbnf.h" michael@0: #include "unicode/ustring.h" michael@0: #include "unicode/fmtable.h" michael@0: #include "unicode/dcfmtsym.h" michael@0: #include "unicode/curramt.h" michael@0: #include "unicode/localpointer.h" michael@0: #include "uassert.h" michael@0: #include "cpputils.h" michael@0: #include "cstring.h" michael@0: michael@0: michael@0: U_NAMESPACE_USE michael@0: michael@0: michael@0: U_CAPI UNumberFormat* U_EXPORT2 michael@0: unum_open( UNumberFormatStyle style, michael@0: const UChar* pattern, michael@0: int32_t patternLength, michael@0: const char* locale, michael@0: UParseError* parseErr, michael@0: UErrorCode* status) { michael@0: if(U_FAILURE(*status)) { michael@0: return NULL; michael@0: } michael@0: michael@0: NumberFormat *retVal = NULL; michael@0: michael@0: switch(style) { michael@0: case UNUM_DECIMAL: michael@0: case UNUM_CURRENCY: michael@0: case UNUM_PERCENT: michael@0: case UNUM_SCIENTIFIC: michael@0: retVal = NumberFormat::createInstance(Locale(locale), style, *status); michael@0: break; michael@0: michael@0: case UNUM_PATTERN_DECIMAL: { michael@0: UParseError tErr; michael@0: /* UnicodeString can handle the case when patternLength = -1. */ michael@0: const UnicodeString pat(pattern, patternLength); michael@0: michael@0: if(parseErr==NULL){ michael@0: parseErr = &tErr; michael@0: } michael@0: michael@0: DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status); michael@0: if(syms == NULL) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return NULL; michael@0: } michael@0: if (U_FAILURE(*status)) { michael@0: delete syms; michael@0: return NULL; michael@0: } michael@0: michael@0: retVal = new DecimalFormat(pat, syms, *parseErr, *status); michael@0: if(retVal == NULL) { michael@0: delete syms; michael@0: } michael@0: } break; michael@0: michael@0: #if U_HAVE_RBNF michael@0: case UNUM_PATTERN_RULEBASED: { michael@0: UParseError tErr; michael@0: /* UnicodeString can handle the case when patternLength = -1. */ michael@0: const UnicodeString pat(pattern, patternLength); michael@0: michael@0: if(parseErr==NULL){ michael@0: parseErr = &tErr; michael@0: } michael@0: michael@0: retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status); michael@0: } break; michael@0: michael@0: case UNUM_SPELLOUT: michael@0: retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status); michael@0: break; michael@0: michael@0: case UNUM_ORDINAL: michael@0: retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status); michael@0: break; michael@0: michael@0: case UNUM_DURATION: michael@0: retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status); michael@0: break; michael@0: michael@0: case UNUM_NUMBERING_SYSTEM: michael@0: retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status); michael@0: break; michael@0: #endif michael@0: michael@0: default: michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: return NULL; michael@0: } michael@0: michael@0: if(retVal == NULL && U_SUCCESS(*status)) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: } michael@0: michael@0: return reinterpret_cast(retVal); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: unum_close(UNumberFormat* fmt) michael@0: { michael@0: delete (NumberFormat*) fmt; michael@0: } michael@0: michael@0: U_CAPI UNumberFormat* U_EXPORT2 michael@0: unum_clone(const UNumberFormat *fmt, michael@0: UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) michael@0: return 0; michael@0: michael@0: Format *res = 0; michael@0: const NumberFormat* nf = reinterpret_cast(fmt); michael@0: const DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL) { michael@0: res = df->clone(); michael@0: } else { michael@0: const RuleBasedNumberFormat* rbnf = dynamic_cast(nf); michael@0: U_ASSERT(rbnf != NULL); michael@0: res = rbnf->clone(); michael@0: } michael@0: michael@0: if(res == 0) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return 0; michael@0: } michael@0: michael@0: return (UNumberFormat*) res; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_format( const UNumberFormat* fmt, michael@0: int32_t number, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UFieldPosition *pos, michael@0: UErrorCode* status) michael@0: { michael@0: return unum_formatInt64(fmt, number, result, resultLength, pos, status); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_formatInt64(const UNumberFormat* fmt, michael@0: int64_t number, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UFieldPosition *pos, michael@0: UErrorCode* status) michael@0: { michael@0: if(U_FAILURE(*status)) michael@0: return -1; michael@0: michael@0: UnicodeString res; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: res.setTo(result, 0, resultLength); michael@0: } michael@0: michael@0: FieldPosition fp; michael@0: michael@0: if(pos != 0) michael@0: fp.setField(pos->field); michael@0: michael@0: ((const NumberFormat*)fmt)->format(number, res, fp, *status); michael@0: michael@0: if(pos != 0) { michael@0: pos->beginIndex = fp.getBeginIndex(); michael@0: pos->endIndex = fp.getEndIndex(); michael@0: } michael@0: michael@0: return res.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_formatDouble( const UNumberFormat* fmt, michael@0: double number, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UFieldPosition *pos, /* 0 if ignore */ michael@0: UErrorCode* status) michael@0: { michael@0: michael@0: if(U_FAILURE(*status)) return -1; michael@0: michael@0: UnicodeString res; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: res.setTo(result, 0, resultLength); michael@0: } michael@0: michael@0: FieldPosition fp; michael@0: michael@0: if(pos != 0) michael@0: fp.setField(pos->field); michael@0: michael@0: ((const NumberFormat*)fmt)->format(number, res, fp, *status); michael@0: michael@0: if(pos != 0) { michael@0: pos->beginIndex = fp.getBeginIndex(); michael@0: pos->endIndex = fp.getEndIndex(); michael@0: } michael@0: michael@0: return res.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_formatDecimal(const UNumberFormat* fmt, michael@0: const char * number, michael@0: int32_t length, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UFieldPosition *pos, /* 0 if ignore */ michael@0: UErrorCode* status) { michael@0: michael@0: if(U_FAILURE(*status)) { michael@0: return -1; michael@0: } michael@0: if ((result == NULL && resultLength != 0) || resultLength < 0) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: return -1; michael@0: } michael@0: michael@0: FieldPosition fp; michael@0: if(pos != 0) { michael@0: fp.setField(pos->field); michael@0: } michael@0: michael@0: if (length < 0) { michael@0: length = uprv_strlen(number); michael@0: } michael@0: StringPiece numSP(number, length); michael@0: Formattable numFmtbl(numSP, *status); michael@0: michael@0: UnicodeString resultStr; michael@0: if (resultLength > 0) { michael@0: // Alias the destination buffer. michael@0: resultStr.setTo(result, 0, resultLength); michael@0: } michael@0: ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status); michael@0: if(pos != 0) { michael@0: pos->beginIndex = fp.getBeginIndex(); michael@0: pos->endIndex = fp.getEndIndex(); michael@0: } michael@0: return resultStr.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: michael@0: michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_formatDoubleCurrency(const UNumberFormat* fmt, michael@0: double number, michael@0: UChar* currency, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UFieldPosition* pos, /* ignored if 0 */ michael@0: UErrorCode* status) { michael@0: if (U_FAILURE(*status)) return -1; michael@0: michael@0: UnicodeString res; michael@0: if (!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: res.setTo(result, 0, resultLength); michael@0: } michael@0: michael@0: FieldPosition fp; michael@0: if (pos != 0) { michael@0: fp.setField(pos->field); michael@0: } michael@0: CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status); michael@0: // Check for null pointer. michael@0: if (tempCurrAmnt == NULL) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return -1; michael@0: } michael@0: Formattable n(tempCurrAmnt); michael@0: ((const NumberFormat*)fmt)->format(n, res, fp, *status); michael@0: michael@0: if (pos != 0) { michael@0: pos->beginIndex = fp.getBeginIndex(); michael@0: pos->endIndex = fp.getEndIndex(); michael@0: } michael@0: michael@0: return res.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: static void michael@0: parseRes(Formattable& res, michael@0: const UNumberFormat* fmt, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t *parsePos /* 0 = start */, michael@0: UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) michael@0: return; michael@0: michael@0: const UnicodeString src((UBool)(textLength == -1), text, textLength); michael@0: ParsePosition pp; michael@0: michael@0: if(parsePos != 0) michael@0: pp.setIndex(*parsePos); michael@0: michael@0: ((const NumberFormat*)fmt)->parse(src, res, pp); michael@0: michael@0: if(pp.getErrorIndex() != -1) { michael@0: *status = U_PARSE_ERROR; michael@0: if(parsePos != 0) { michael@0: *parsePos = pp.getErrorIndex(); michael@0: } michael@0: } else if(parsePos != 0) { michael@0: *parsePos = pp.getIndex(); michael@0: } michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_parse( const UNumberFormat* fmt, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t *parsePos /* 0 = start */, michael@0: UErrorCode *status) michael@0: { michael@0: Formattable res; michael@0: parseRes(res, fmt, text, textLength, parsePos, status); michael@0: return res.getLong(*status); michael@0: } michael@0: michael@0: U_CAPI int64_t U_EXPORT2 michael@0: unum_parseInt64( const UNumberFormat* fmt, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t *parsePos /* 0 = start */, michael@0: UErrorCode *status) michael@0: { michael@0: Formattable res; michael@0: parseRes(res, fmt, text, textLength, parsePos, status); michael@0: return res.getInt64(*status); michael@0: } michael@0: michael@0: U_CAPI double U_EXPORT2 michael@0: unum_parseDouble( const UNumberFormat* fmt, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t *parsePos /* 0 = start */, michael@0: UErrorCode *status) michael@0: { michael@0: Formattable res; michael@0: parseRes(res, fmt, text, textLength, parsePos, status); michael@0: return res.getDouble(*status); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_parseDecimal(const UNumberFormat* fmt, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t *parsePos /* 0 = start */, michael@0: char *outBuf, michael@0: int32_t outBufLength, michael@0: UErrorCode *status) michael@0: { michael@0: if (U_FAILURE(*status)) { michael@0: return -1; michael@0: } michael@0: if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: return -1; michael@0: } michael@0: Formattable res; michael@0: parseRes(res, fmt, text, textLength, parsePos, status); michael@0: StringPiece sp = res.getDecimalNumber(*status); michael@0: if (U_FAILURE(*status)) { michael@0: return -1; michael@0: } else if (sp.size() > outBufLength) { michael@0: *status = U_BUFFER_OVERFLOW_ERROR; michael@0: } else if (sp.size() == outBufLength) { michael@0: uprv_strncpy(outBuf, sp.data(), sp.size()); michael@0: *status = U_STRING_NOT_TERMINATED_WARNING; michael@0: } else { michael@0: U_ASSERT(outBufLength > 0); michael@0: uprv_strcpy(outBuf, sp.data()); michael@0: } michael@0: return sp.size(); michael@0: } michael@0: michael@0: U_CAPI double U_EXPORT2 michael@0: unum_parseDoubleCurrency(const UNumberFormat* fmt, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t* parsePos, /* 0 = start */ michael@0: UChar* currency, michael@0: UErrorCode* status) { michael@0: double doubleVal = 0.0; michael@0: currency[0] = 0; michael@0: if (U_FAILURE(*status)) { michael@0: return doubleVal; michael@0: } michael@0: const UnicodeString src((UBool)(textLength == -1), text, textLength); michael@0: ParsePosition pp; michael@0: if (parsePos != NULL) { michael@0: pp.setIndex(*parsePos); michael@0: } michael@0: *status = U_PARSE_ERROR; // assume failure, reset if succeed michael@0: LocalPointer currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp)); michael@0: if (pp.getErrorIndex() != -1) { michael@0: if (parsePos != NULL) { michael@0: *parsePos = pp.getErrorIndex(); michael@0: } michael@0: } else { michael@0: if (parsePos != NULL) { michael@0: *parsePos = pp.getIndex(); michael@0: } michael@0: if (pp.getIndex() > 0) { michael@0: *status = U_ZERO_ERROR; michael@0: u_strcpy(currency, currAmt->getISOCurrency()); michael@0: doubleVal = currAmt->getNumber().getDouble(*status); michael@0: } michael@0: } michael@0: return doubleVal; michael@0: } michael@0: michael@0: U_CAPI const char* U_EXPORT2 michael@0: unum_getAvailable(int32_t index) michael@0: { michael@0: return uloc_getAvailable(index); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_countAvailable() michael@0: { michael@0: return uloc_countAvailable(); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_getAttribute(const UNumberFormat* fmt, michael@0: UNumberFormatAttribute attr) michael@0: { michael@0: const NumberFormat* nf = reinterpret_cast(fmt); michael@0: if ( attr == UNUM_LENIENT_PARSE ) { michael@0: // Supported for all subclasses michael@0: return nf->isLenient(); michael@0: } michael@0: michael@0: // The remaining attributea are only supported for DecimalFormat michael@0: const DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL) { michael@0: UErrorCode ignoredStatus = U_ZERO_ERROR; michael@0: return df->getAttribute( attr, ignoredStatus ); michael@0: } michael@0: michael@0: return -1; michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: unum_setAttribute( UNumberFormat* fmt, michael@0: UNumberFormatAttribute attr, michael@0: int32_t newValue) michael@0: { michael@0: NumberFormat* nf = reinterpret_cast(fmt); michael@0: if ( attr == UNUM_LENIENT_PARSE ) { michael@0: // Supported for all subclasses michael@0: // keep this here as the class may not be a DecimalFormat michael@0: return nf->setLenient(newValue != 0); michael@0: } michael@0: // The remaining attributea are only supported for DecimalFormat michael@0: DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL) { michael@0: UErrorCode ignoredStatus = U_ZERO_ERROR; michael@0: df->setAttribute(attr, newValue, ignoredStatus); michael@0: } michael@0: } michael@0: michael@0: U_CAPI double U_EXPORT2 michael@0: unum_getDoubleAttribute(const UNumberFormat* fmt, michael@0: UNumberFormatAttribute attr) michael@0: { michael@0: const NumberFormat* nf = reinterpret_cast(fmt); michael@0: const DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { michael@0: return df->getRoundingIncrement(); michael@0: } else { michael@0: return -1.0; michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: unum_setDoubleAttribute( UNumberFormat* fmt, michael@0: UNumberFormatAttribute attr, michael@0: double newValue) michael@0: { michael@0: NumberFormat* nf = reinterpret_cast(fmt); michael@0: DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { michael@0: df->setRoundingIncrement(newValue); michael@0: } michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_getTextAttribute(const UNumberFormat* fmt, michael@0: UNumberFormatTextAttribute tag, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UErrorCode* status) michael@0: { michael@0: if(U_FAILURE(*status)) michael@0: return -1; michael@0: michael@0: UnicodeString res; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: res.setTo(result, 0, resultLength); michael@0: } michael@0: michael@0: const NumberFormat* nf = reinterpret_cast(fmt); michael@0: const DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL) { michael@0: switch(tag) { michael@0: case UNUM_POSITIVE_PREFIX: michael@0: df->getPositivePrefix(res); michael@0: break; michael@0: michael@0: case UNUM_POSITIVE_SUFFIX: michael@0: df->getPositiveSuffix(res); michael@0: break; michael@0: michael@0: case UNUM_NEGATIVE_PREFIX: michael@0: df->getNegativePrefix(res); michael@0: break; michael@0: michael@0: case UNUM_NEGATIVE_SUFFIX: michael@0: df->getNegativeSuffix(res); michael@0: break; michael@0: michael@0: case UNUM_PADDING_CHARACTER: michael@0: res = df->getPadCharacterString(); michael@0: break; michael@0: michael@0: case UNUM_CURRENCY_CODE: michael@0: res = UnicodeString(df->getCurrency()); michael@0: break; michael@0: michael@0: default: michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: return -1; michael@0: } michael@0: } else { michael@0: const RuleBasedNumberFormat* rbnf = dynamic_cast(nf); michael@0: U_ASSERT(rbnf != NULL); michael@0: if (tag == UNUM_DEFAULT_RULESET) { michael@0: res = rbnf->getDefaultRuleSetName(); michael@0: } else if (tag == UNUM_PUBLIC_RULESETS) { michael@0: int32_t count = rbnf->getNumberOfRuleSetNames(); michael@0: for (int i = 0; i < count; ++i) { michael@0: res += rbnf->getRuleSetName(i); michael@0: res += (UChar)0x003b; // semicolon michael@0: } michael@0: } else { michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: return -1; michael@0: } michael@0: } michael@0: michael@0: return res.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: unum_setTextAttribute( UNumberFormat* fmt, michael@0: UNumberFormatTextAttribute tag, michael@0: const UChar* newValue, michael@0: int32_t newValueLength, michael@0: UErrorCode *status) michael@0: { michael@0: if(U_FAILURE(*status)) michael@0: return; michael@0: michael@0: UnicodeString val(newValue, newValueLength); michael@0: NumberFormat* nf = reinterpret_cast(fmt); michael@0: DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL) { michael@0: switch(tag) { michael@0: case UNUM_POSITIVE_PREFIX: michael@0: df->setPositivePrefix(val); michael@0: break; michael@0: michael@0: case UNUM_POSITIVE_SUFFIX: michael@0: df->setPositiveSuffix(val); michael@0: break; michael@0: michael@0: case UNUM_NEGATIVE_PREFIX: michael@0: df->setNegativePrefix(val); michael@0: break; michael@0: michael@0: case UNUM_NEGATIVE_SUFFIX: michael@0: df->setNegativeSuffix(val); michael@0: break; michael@0: michael@0: case UNUM_PADDING_CHARACTER: michael@0: df->setPadCharacter(val); michael@0: break; michael@0: michael@0: case UNUM_CURRENCY_CODE: michael@0: df->setCurrency(val.getTerminatedBuffer(), *status); michael@0: break; michael@0: michael@0: default: michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: break; michael@0: } michael@0: } else { michael@0: RuleBasedNumberFormat* rbnf = dynamic_cast(nf); michael@0: U_ASSERT(rbnf != NULL); michael@0: if (tag == UNUM_DEFAULT_RULESET) { michael@0: rbnf->setDefaultRuleSet(val, *status); michael@0: } else { michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: } michael@0: } michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_toPattern( const UNumberFormat* fmt, michael@0: UBool isPatternLocalized, michael@0: UChar* result, michael@0: int32_t resultLength, michael@0: UErrorCode* status) michael@0: { michael@0: if(U_FAILURE(*status)) michael@0: return -1; michael@0: michael@0: UnicodeString pat; michael@0: if(!(result==NULL && resultLength==0)) { michael@0: // NULL destination for pure preflighting: empty dummy string michael@0: // otherwise, alias the destination buffer michael@0: pat.setTo(result, 0, resultLength); michael@0: } michael@0: michael@0: const NumberFormat* nf = reinterpret_cast(fmt); michael@0: const DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL) { michael@0: if(isPatternLocalized) michael@0: df->toLocalizedPattern(pat); michael@0: else michael@0: df->toPattern(pat); michael@0: } else { michael@0: const RuleBasedNumberFormat* rbnf = dynamic_cast(nf); michael@0: U_ASSERT(rbnf != NULL); michael@0: pat = rbnf->getRules(); michael@0: } michael@0: return pat.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 michael@0: unum_getSymbol(const UNumberFormat *fmt, michael@0: UNumberFormatSymbol symbol, michael@0: UChar *buffer, michael@0: int32_t size, michael@0: UErrorCode *status) michael@0: { michael@0: if(status==NULL || U_FAILURE(*status)) { michael@0: return 0; michael@0: } michael@0: if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { michael@0: *status=U_ILLEGAL_ARGUMENT_ERROR; michael@0: return 0; michael@0: } michael@0: const NumberFormat *nf = reinterpret_cast(fmt); michael@0: const DecimalFormat *dcf = dynamic_cast(nf); michael@0: if (dcf == NULL) { michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: return 0; michael@0: } michael@0: michael@0: return dcf-> michael@0: getDecimalFormatSymbols()-> michael@0: getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol). michael@0: extract(buffer, size, *status); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: unum_setSymbol(UNumberFormat *fmt, michael@0: UNumberFormatSymbol symbol, michael@0: const UChar *value, michael@0: int32_t length, michael@0: UErrorCode *status) michael@0: { michael@0: if(status==NULL || U_FAILURE(*status)) { michael@0: return; michael@0: } michael@0: if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) { michael@0: *status=U_ILLEGAL_ARGUMENT_ERROR; michael@0: return; michael@0: } michael@0: NumberFormat *nf = reinterpret_cast(fmt); michael@0: DecimalFormat *dcf = dynamic_cast(nf); michael@0: if (dcf == NULL) { michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: return; michael@0: } michael@0: michael@0: DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); michael@0: symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, michael@0: UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ michael@0: dcf->setDecimalFormatSymbols(symbols); michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 michael@0: unum_applyPattern( UNumberFormat *fmt, michael@0: UBool localized, michael@0: const UChar *pattern, michael@0: int32_t patternLength, michael@0: UParseError *parseError, michael@0: UErrorCode* status) michael@0: { michael@0: UErrorCode tStatus = U_ZERO_ERROR; michael@0: UParseError tParseError; michael@0: michael@0: if(parseError == NULL){ michael@0: parseError = &tParseError; michael@0: } michael@0: michael@0: if(status==NULL){ michael@0: status = &tStatus; michael@0: } michael@0: michael@0: int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength); michael@0: const UnicodeString pat((UChar*)pattern, len, len); michael@0: michael@0: // Verify if the object passed is a DecimalFormat object michael@0: NumberFormat* nf = reinterpret_cast(fmt); michael@0: DecimalFormat* df = dynamic_cast(nf); michael@0: if (df != NULL) { michael@0: if(localized) { michael@0: df->applyLocalizedPattern(pat,*parseError, *status); michael@0: } else { michael@0: df->applyPattern(pat,*parseError, *status); michael@0: } michael@0: } else { michael@0: *status = U_UNSUPPORTED_ERROR; michael@0: return; michael@0: } michael@0: } michael@0: michael@0: U_CAPI const char* U_EXPORT2 michael@0: unum_getLocaleByType(const UNumberFormat *fmt, michael@0: ULocDataLocaleType type, michael@0: UErrorCode* status) michael@0: { michael@0: if (fmt == NULL) { michael@0: if (U_SUCCESS(*status)) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: } michael@0: return NULL; michael@0: } michael@0: return ((const Format*)fmt)->getLocaleID(type, *status); michael@0: } michael@0: michael@0: U_INTERNAL UFormattable * U_EXPORT2 michael@0: unum_parseToUFormattable(const UNumberFormat* fmt, michael@0: UFormattable *result, michael@0: const UChar* text, michael@0: int32_t textLength, michael@0: int32_t* parsePos, /* 0 = start */ michael@0: UErrorCode* status) { michael@0: UFormattable *newFormattable = NULL; michael@0: if (U_FAILURE(*status)) return result; michael@0: if (fmt == NULL || (text==NULL && textLength!=0)) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: return result; michael@0: } michael@0: if (result == NULL) { // allocate if not allocated. michael@0: newFormattable = result = ufmt_open(status); michael@0: } michael@0: parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); michael@0: if (U_FAILURE(*status) && newFormattable != NULL) { michael@0: ufmt_close(newFormattable); michael@0: result = NULL; // deallocate if there was a parse error michael@0: } michael@0: return result; michael@0: } michael@0: michael@0: U_INTERNAL int32_t U_EXPORT2 michael@0: unum_formatUFormattable(const UNumberFormat* fmt, michael@0: const UFormattable *number, michael@0: UChar *result, michael@0: int32_t resultLength, michael@0: UFieldPosition *pos, /* ignored if 0 */ michael@0: UErrorCode *status) { michael@0: if (U_FAILURE(*status)) { michael@0: return 0; michael@0: } michael@0: if (fmt == NULL || number==NULL || michael@0: (result==NULL ? resultLength!=0 : resultLength<0)) { michael@0: *status = U_ILLEGAL_ARGUMENT_ERROR; michael@0: return 0; michael@0: } michael@0: UnicodeString res(result, 0, resultLength); michael@0: michael@0: FieldPosition fp; michael@0: michael@0: if(pos != 0) michael@0: fp.setField(pos->field); michael@0: michael@0: ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); michael@0: michael@0: if(pos != 0) { michael@0: pos->beginIndex = fp.getBeginIndex(); michael@0: pos->endIndex = fp.getEndIndex(); michael@0: } michael@0: michael@0: return res.extract(result, resultLength, *status); michael@0: } michael@0: michael@0: #endif /* #if !UCONFIG_NO_FORMATTING */