1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/unum.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,842 @@ 1.4 +/* 1.5 +******************************************************************************* 1.6 +* Copyright (C) 1996-2013, International Business Machines 1.7 +* Corporation and others. All Rights Reserved. 1.8 +******************************************************************************* 1.9 +* Modification History: 1.10 +* 1.11 +* Date Name Description 1.12 +* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes 1.13 +******************************************************************************* 1.14 +*/ 1.15 + 1.16 +#include "unicode/utypes.h" 1.17 + 1.18 +#if !UCONFIG_NO_FORMATTING 1.19 + 1.20 +#include "unicode/unum.h" 1.21 + 1.22 +#include "unicode/uloc.h" 1.23 +#include "unicode/numfmt.h" 1.24 +#include "unicode/decimfmt.h" 1.25 +#include "unicode/rbnf.h" 1.26 +#include "unicode/ustring.h" 1.27 +#include "unicode/fmtable.h" 1.28 +#include "unicode/dcfmtsym.h" 1.29 +#include "unicode/curramt.h" 1.30 +#include "unicode/localpointer.h" 1.31 +#include "uassert.h" 1.32 +#include "cpputils.h" 1.33 +#include "cstring.h" 1.34 + 1.35 + 1.36 +U_NAMESPACE_USE 1.37 + 1.38 + 1.39 +U_CAPI UNumberFormat* U_EXPORT2 1.40 +unum_open( UNumberFormatStyle style, 1.41 + const UChar* pattern, 1.42 + int32_t patternLength, 1.43 + const char* locale, 1.44 + UParseError* parseErr, 1.45 + UErrorCode* status) { 1.46 + if(U_FAILURE(*status)) { 1.47 + return NULL; 1.48 + } 1.49 + 1.50 + NumberFormat *retVal = NULL; 1.51 + 1.52 + switch(style) { 1.53 + case UNUM_DECIMAL: 1.54 + case UNUM_CURRENCY: 1.55 + case UNUM_PERCENT: 1.56 + case UNUM_SCIENTIFIC: 1.57 + retVal = NumberFormat::createInstance(Locale(locale), style, *status); 1.58 + break; 1.59 + 1.60 + case UNUM_PATTERN_DECIMAL: { 1.61 + UParseError tErr; 1.62 + /* UnicodeString can handle the case when patternLength = -1. */ 1.63 + const UnicodeString pat(pattern, patternLength); 1.64 + 1.65 + if(parseErr==NULL){ 1.66 + parseErr = &tErr; 1.67 + } 1.68 + 1.69 + DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status); 1.70 + if(syms == NULL) { 1.71 + *status = U_MEMORY_ALLOCATION_ERROR; 1.72 + return NULL; 1.73 + } 1.74 + if (U_FAILURE(*status)) { 1.75 + delete syms; 1.76 + return NULL; 1.77 + } 1.78 + 1.79 + retVal = new DecimalFormat(pat, syms, *parseErr, *status); 1.80 + if(retVal == NULL) { 1.81 + delete syms; 1.82 + } 1.83 + } break; 1.84 + 1.85 +#if U_HAVE_RBNF 1.86 + case UNUM_PATTERN_RULEBASED: { 1.87 + UParseError tErr; 1.88 + /* UnicodeString can handle the case when patternLength = -1. */ 1.89 + const UnicodeString pat(pattern, patternLength); 1.90 + 1.91 + if(parseErr==NULL){ 1.92 + parseErr = &tErr; 1.93 + } 1.94 + 1.95 + retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status); 1.96 + } break; 1.97 + 1.98 + case UNUM_SPELLOUT: 1.99 + retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status); 1.100 + break; 1.101 + 1.102 + case UNUM_ORDINAL: 1.103 + retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status); 1.104 + break; 1.105 + 1.106 + case UNUM_DURATION: 1.107 + retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status); 1.108 + break; 1.109 + 1.110 + case UNUM_NUMBERING_SYSTEM: 1.111 + retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status); 1.112 + break; 1.113 +#endif 1.114 + 1.115 + default: 1.116 + *status = U_UNSUPPORTED_ERROR; 1.117 + return NULL; 1.118 + } 1.119 + 1.120 + if(retVal == NULL && U_SUCCESS(*status)) { 1.121 + *status = U_MEMORY_ALLOCATION_ERROR; 1.122 + } 1.123 + 1.124 + return reinterpret_cast<UNumberFormat *>(retVal); 1.125 +} 1.126 + 1.127 +U_CAPI void U_EXPORT2 1.128 +unum_close(UNumberFormat* fmt) 1.129 +{ 1.130 + delete (NumberFormat*) fmt; 1.131 +} 1.132 + 1.133 +U_CAPI UNumberFormat* U_EXPORT2 1.134 +unum_clone(const UNumberFormat *fmt, 1.135 + UErrorCode *status) 1.136 +{ 1.137 + if(U_FAILURE(*status)) 1.138 + return 0; 1.139 + 1.140 + Format *res = 0; 1.141 + const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 1.142 + const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 1.143 + if (df != NULL) { 1.144 + res = df->clone(); 1.145 + } else { 1.146 + const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 1.147 + U_ASSERT(rbnf != NULL); 1.148 + res = rbnf->clone(); 1.149 + } 1.150 + 1.151 + if(res == 0) { 1.152 + *status = U_MEMORY_ALLOCATION_ERROR; 1.153 + return 0; 1.154 + } 1.155 + 1.156 + return (UNumberFormat*) res; 1.157 +} 1.158 + 1.159 +U_CAPI int32_t U_EXPORT2 1.160 +unum_format( const UNumberFormat* fmt, 1.161 + int32_t number, 1.162 + UChar* result, 1.163 + int32_t resultLength, 1.164 + UFieldPosition *pos, 1.165 + UErrorCode* status) 1.166 +{ 1.167 + return unum_formatInt64(fmt, number, result, resultLength, pos, status); 1.168 +} 1.169 + 1.170 +U_CAPI int32_t U_EXPORT2 1.171 +unum_formatInt64(const UNumberFormat* fmt, 1.172 + int64_t number, 1.173 + UChar* result, 1.174 + int32_t resultLength, 1.175 + UFieldPosition *pos, 1.176 + UErrorCode* status) 1.177 +{ 1.178 + if(U_FAILURE(*status)) 1.179 + return -1; 1.180 + 1.181 + UnicodeString res; 1.182 + if(!(result==NULL && resultLength==0)) { 1.183 + // NULL destination for pure preflighting: empty dummy string 1.184 + // otherwise, alias the destination buffer 1.185 + res.setTo(result, 0, resultLength); 1.186 + } 1.187 + 1.188 + FieldPosition fp; 1.189 + 1.190 + if(pos != 0) 1.191 + fp.setField(pos->field); 1.192 + 1.193 + ((const NumberFormat*)fmt)->format(number, res, fp, *status); 1.194 + 1.195 + if(pos != 0) { 1.196 + pos->beginIndex = fp.getBeginIndex(); 1.197 + pos->endIndex = fp.getEndIndex(); 1.198 + } 1.199 + 1.200 + return res.extract(result, resultLength, *status); 1.201 +} 1.202 + 1.203 +U_CAPI int32_t U_EXPORT2 1.204 +unum_formatDouble( const UNumberFormat* fmt, 1.205 + double number, 1.206 + UChar* result, 1.207 + int32_t resultLength, 1.208 + UFieldPosition *pos, /* 0 if ignore */ 1.209 + UErrorCode* status) 1.210 +{ 1.211 + 1.212 + if(U_FAILURE(*status)) return -1; 1.213 + 1.214 + UnicodeString res; 1.215 + if(!(result==NULL && resultLength==0)) { 1.216 + // NULL destination for pure preflighting: empty dummy string 1.217 + // otherwise, alias the destination buffer 1.218 + res.setTo(result, 0, resultLength); 1.219 + } 1.220 + 1.221 + FieldPosition fp; 1.222 + 1.223 + if(pos != 0) 1.224 + fp.setField(pos->field); 1.225 + 1.226 + ((const NumberFormat*)fmt)->format(number, res, fp, *status); 1.227 + 1.228 + if(pos != 0) { 1.229 + pos->beginIndex = fp.getBeginIndex(); 1.230 + pos->endIndex = fp.getEndIndex(); 1.231 + } 1.232 + 1.233 + return res.extract(result, resultLength, *status); 1.234 +} 1.235 + 1.236 + 1.237 +U_CAPI int32_t U_EXPORT2 1.238 +unum_formatDecimal(const UNumberFormat* fmt, 1.239 + const char * number, 1.240 + int32_t length, 1.241 + UChar* result, 1.242 + int32_t resultLength, 1.243 + UFieldPosition *pos, /* 0 if ignore */ 1.244 + UErrorCode* status) { 1.245 + 1.246 + if(U_FAILURE(*status)) { 1.247 + return -1; 1.248 + } 1.249 + if ((result == NULL && resultLength != 0) || resultLength < 0) { 1.250 + *status = U_ILLEGAL_ARGUMENT_ERROR; 1.251 + return -1; 1.252 + } 1.253 + 1.254 + FieldPosition fp; 1.255 + if(pos != 0) { 1.256 + fp.setField(pos->field); 1.257 + } 1.258 + 1.259 + if (length < 0) { 1.260 + length = uprv_strlen(number); 1.261 + } 1.262 + StringPiece numSP(number, length); 1.263 + Formattable numFmtbl(numSP, *status); 1.264 + 1.265 + UnicodeString resultStr; 1.266 + if (resultLength > 0) { 1.267 + // Alias the destination buffer. 1.268 + resultStr.setTo(result, 0, resultLength); 1.269 + } 1.270 + ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status); 1.271 + if(pos != 0) { 1.272 + pos->beginIndex = fp.getBeginIndex(); 1.273 + pos->endIndex = fp.getEndIndex(); 1.274 + } 1.275 + return resultStr.extract(result, resultLength, *status); 1.276 +} 1.277 + 1.278 + 1.279 + 1.280 + 1.281 +U_CAPI int32_t U_EXPORT2 1.282 +unum_formatDoubleCurrency(const UNumberFormat* fmt, 1.283 + double number, 1.284 + UChar* currency, 1.285 + UChar* result, 1.286 + int32_t resultLength, 1.287 + UFieldPosition* pos, /* ignored if 0 */ 1.288 + UErrorCode* status) { 1.289 + if (U_FAILURE(*status)) return -1; 1.290 + 1.291 + UnicodeString res; 1.292 + if (!(result==NULL && resultLength==0)) { 1.293 + // NULL destination for pure preflighting: empty dummy string 1.294 + // otherwise, alias the destination buffer 1.295 + res.setTo(result, 0, resultLength); 1.296 + } 1.297 + 1.298 + FieldPosition fp; 1.299 + if (pos != 0) { 1.300 + fp.setField(pos->field); 1.301 + } 1.302 + CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status); 1.303 + // Check for null pointer. 1.304 + if (tempCurrAmnt == NULL) { 1.305 + *status = U_MEMORY_ALLOCATION_ERROR; 1.306 + return -1; 1.307 + } 1.308 + Formattable n(tempCurrAmnt); 1.309 + ((const NumberFormat*)fmt)->format(n, res, fp, *status); 1.310 + 1.311 + if (pos != 0) { 1.312 + pos->beginIndex = fp.getBeginIndex(); 1.313 + pos->endIndex = fp.getEndIndex(); 1.314 + } 1.315 + 1.316 + return res.extract(result, resultLength, *status); 1.317 +} 1.318 + 1.319 +static void 1.320 +parseRes(Formattable& res, 1.321 + const UNumberFormat* fmt, 1.322 + const UChar* text, 1.323 + int32_t textLength, 1.324 + int32_t *parsePos /* 0 = start */, 1.325 + UErrorCode *status) 1.326 +{ 1.327 + if(U_FAILURE(*status)) 1.328 + return; 1.329 + 1.330 + const UnicodeString src((UBool)(textLength == -1), text, textLength); 1.331 + ParsePosition pp; 1.332 + 1.333 + if(parsePos != 0) 1.334 + pp.setIndex(*parsePos); 1.335 + 1.336 + ((const NumberFormat*)fmt)->parse(src, res, pp); 1.337 + 1.338 + if(pp.getErrorIndex() != -1) { 1.339 + *status = U_PARSE_ERROR; 1.340 + if(parsePos != 0) { 1.341 + *parsePos = pp.getErrorIndex(); 1.342 + } 1.343 + } else if(parsePos != 0) { 1.344 + *parsePos = pp.getIndex(); 1.345 + } 1.346 +} 1.347 + 1.348 +U_CAPI int32_t U_EXPORT2 1.349 +unum_parse( const UNumberFormat* fmt, 1.350 + const UChar* text, 1.351 + int32_t textLength, 1.352 + int32_t *parsePos /* 0 = start */, 1.353 + UErrorCode *status) 1.354 +{ 1.355 + Formattable res; 1.356 + parseRes(res, fmt, text, textLength, parsePos, status); 1.357 + return res.getLong(*status); 1.358 +} 1.359 + 1.360 +U_CAPI int64_t U_EXPORT2 1.361 +unum_parseInt64( const UNumberFormat* fmt, 1.362 + const UChar* text, 1.363 + int32_t textLength, 1.364 + int32_t *parsePos /* 0 = start */, 1.365 + UErrorCode *status) 1.366 +{ 1.367 + Formattable res; 1.368 + parseRes(res, fmt, text, textLength, parsePos, status); 1.369 + return res.getInt64(*status); 1.370 +} 1.371 + 1.372 +U_CAPI double U_EXPORT2 1.373 +unum_parseDouble( const UNumberFormat* fmt, 1.374 + const UChar* text, 1.375 + int32_t textLength, 1.376 + int32_t *parsePos /* 0 = start */, 1.377 + UErrorCode *status) 1.378 +{ 1.379 + Formattable res; 1.380 + parseRes(res, fmt, text, textLength, parsePos, status); 1.381 + return res.getDouble(*status); 1.382 +} 1.383 + 1.384 +U_CAPI int32_t U_EXPORT2 1.385 +unum_parseDecimal(const UNumberFormat* fmt, 1.386 + const UChar* text, 1.387 + int32_t textLength, 1.388 + int32_t *parsePos /* 0 = start */, 1.389 + char *outBuf, 1.390 + int32_t outBufLength, 1.391 + UErrorCode *status) 1.392 +{ 1.393 + if (U_FAILURE(*status)) { 1.394 + return -1; 1.395 + } 1.396 + if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) { 1.397 + *status = U_ILLEGAL_ARGUMENT_ERROR; 1.398 + return -1; 1.399 + } 1.400 + Formattable res; 1.401 + parseRes(res, fmt, text, textLength, parsePos, status); 1.402 + StringPiece sp = res.getDecimalNumber(*status); 1.403 + if (U_FAILURE(*status)) { 1.404 + return -1; 1.405 + } else if (sp.size() > outBufLength) { 1.406 + *status = U_BUFFER_OVERFLOW_ERROR; 1.407 + } else if (sp.size() == outBufLength) { 1.408 + uprv_strncpy(outBuf, sp.data(), sp.size()); 1.409 + *status = U_STRING_NOT_TERMINATED_WARNING; 1.410 + } else { 1.411 + U_ASSERT(outBufLength > 0); 1.412 + uprv_strcpy(outBuf, sp.data()); 1.413 + } 1.414 + return sp.size(); 1.415 +} 1.416 + 1.417 +U_CAPI double U_EXPORT2 1.418 +unum_parseDoubleCurrency(const UNumberFormat* fmt, 1.419 + const UChar* text, 1.420 + int32_t textLength, 1.421 + int32_t* parsePos, /* 0 = start */ 1.422 + UChar* currency, 1.423 + UErrorCode* status) { 1.424 + double doubleVal = 0.0; 1.425 + currency[0] = 0; 1.426 + if (U_FAILURE(*status)) { 1.427 + return doubleVal; 1.428 + } 1.429 + const UnicodeString src((UBool)(textLength == -1), text, textLength); 1.430 + ParsePosition pp; 1.431 + if (parsePos != NULL) { 1.432 + pp.setIndex(*parsePos); 1.433 + } 1.434 + *status = U_PARSE_ERROR; // assume failure, reset if succeed 1.435 + LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp)); 1.436 + if (pp.getErrorIndex() != -1) { 1.437 + if (parsePos != NULL) { 1.438 + *parsePos = pp.getErrorIndex(); 1.439 + } 1.440 + } else { 1.441 + if (parsePos != NULL) { 1.442 + *parsePos = pp.getIndex(); 1.443 + } 1.444 + if (pp.getIndex() > 0) { 1.445 + *status = U_ZERO_ERROR; 1.446 + u_strcpy(currency, currAmt->getISOCurrency()); 1.447 + doubleVal = currAmt->getNumber().getDouble(*status); 1.448 + } 1.449 + } 1.450 + return doubleVal; 1.451 +} 1.452 + 1.453 +U_CAPI const char* U_EXPORT2 1.454 +unum_getAvailable(int32_t index) 1.455 +{ 1.456 + return uloc_getAvailable(index); 1.457 +} 1.458 + 1.459 +U_CAPI int32_t U_EXPORT2 1.460 +unum_countAvailable() 1.461 +{ 1.462 + return uloc_countAvailable(); 1.463 +} 1.464 + 1.465 +U_CAPI int32_t U_EXPORT2 1.466 +unum_getAttribute(const UNumberFormat* fmt, 1.467 + UNumberFormatAttribute attr) 1.468 +{ 1.469 + const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 1.470 + if ( attr == UNUM_LENIENT_PARSE ) { 1.471 + // Supported for all subclasses 1.472 + return nf->isLenient(); 1.473 + } 1.474 + 1.475 + // The remaining attributea are only supported for DecimalFormat 1.476 + const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 1.477 + if (df != NULL) { 1.478 + UErrorCode ignoredStatus = U_ZERO_ERROR; 1.479 + return df->getAttribute( attr, ignoredStatus ); 1.480 + } 1.481 + 1.482 + return -1; 1.483 +} 1.484 + 1.485 +U_CAPI void U_EXPORT2 1.486 +unum_setAttribute( UNumberFormat* fmt, 1.487 + UNumberFormatAttribute attr, 1.488 + int32_t newValue) 1.489 +{ 1.490 + NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 1.491 + if ( attr == UNUM_LENIENT_PARSE ) { 1.492 + // Supported for all subclasses 1.493 + // keep this here as the class may not be a DecimalFormat 1.494 + return nf->setLenient(newValue != 0); 1.495 + } 1.496 + // The remaining attributea are only supported for DecimalFormat 1.497 + DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 1.498 + if (df != NULL) { 1.499 + UErrorCode ignoredStatus = U_ZERO_ERROR; 1.500 + df->setAttribute(attr, newValue, ignoredStatus); 1.501 + } 1.502 +} 1.503 + 1.504 +U_CAPI double U_EXPORT2 1.505 +unum_getDoubleAttribute(const UNumberFormat* fmt, 1.506 + UNumberFormatAttribute attr) 1.507 +{ 1.508 + const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 1.509 + const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 1.510 + if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { 1.511 + return df->getRoundingIncrement(); 1.512 + } else { 1.513 + return -1.0; 1.514 + } 1.515 +} 1.516 + 1.517 +U_CAPI void U_EXPORT2 1.518 +unum_setDoubleAttribute( UNumberFormat* fmt, 1.519 + UNumberFormatAttribute attr, 1.520 + double newValue) 1.521 +{ 1.522 + NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 1.523 + DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 1.524 + if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { 1.525 + df->setRoundingIncrement(newValue); 1.526 + } 1.527 +} 1.528 + 1.529 +U_CAPI int32_t U_EXPORT2 1.530 +unum_getTextAttribute(const UNumberFormat* fmt, 1.531 + UNumberFormatTextAttribute tag, 1.532 + UChar* result, 1.533 + int32_t resultLength, 1.534 + UErrorCode* status) 1.535 +{ 1.536 + if(U_FAILURE(*status)) 1.537 + return -1; 1.538 + 1.539 + UnicodeString res; 1.540 + if(!(result==NULL && resultLength==0)) { 1.541 + // NULL destination for pure preflighting: empty dummy string 1.542 + // otherwise, alias the destination buffer 1.543 + res.setTo(result, 0, resultLength); 1.544 + } 1.545 + 1.546 + const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 1.547 + const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 1.548 + if (df != NULL) { 1.549 + switch(tag) { 1.550 + case UNUM_POSITIVE_PREFIX: 1.551 + df->getPositivePrefix(res); 1.552 + break; 1.553 + 1.554 + case UNUM_POSITIVE_SUFFIX: 1.555 + df->getPositiveSuffix(res); 1.556 + break; 1.557 + 1.558 + case UNUM_NEGATIVE_PREFIX: 1.559 + df->getNegativePrefix(res); 1.560 + break; 1.561 + 1.562 + case UNUM_NEGATIVE_SUFFIX: 1.563 + df->getNegativeSuffix(res); 1.564 + break; 1.565 + 1.566 + case UNUM_PADDING_CHARACTER: 1.567 + res = df->getPadCharacterString(); 1.568 + break; 1.569 + 1.570 + case UNUM_CURRENCY_CODE: 1.571 + res = UnicodeString(df->getCurrency()); 1.572 + break; 1.573 + 1.574 + default: 1.575 + *status = U_UNSUPPORTED_ERROR; 1.576 + return -1; 1.577 + } 1.578 + } else { 1.579 + const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 1.580 + U_ASSERT(rbnf != NULL); 1.581 + if (tag == UNUM_DEFAULT_RULESET) { 1.582 + res = rbnf->getDefaultRuleSetName(); 1.583 + } else if (tag == UNUM_PUBLIC_RULESETS) { 1.584 + int32_t count = rbnf->getNumberOfRuleSetNames(); 1.585 + for (int i = 0; i < count; ++i) { 1.586 + res += rbnf->getRuleSetName(i); 1.587 + res += (UChar)0x003b; // semicolon 1.588 + } 1.589 + } else { 1.590 + *status = U_UNSUPPORTED_ERROR; 1.591 + return -1; 1.592 + } 1.593 + } 1.594 + 1.595 + return res.extract(result, resultLength, *status); 1.596 +} 1.597 + 1.598 +U_CAPI void U_EXPORT2 1.599 +unum_setTextAttribute( UNumberFormat* fmt, 1.600 + UNumberFormatTextAttribute tag, 1.601 + const UChar* newValue, 1.602 + int32_t newValueLength, 1.603 + UErrorCode *status) 1.604 +{ 1.605 + if(U_FAILURE(*status)) 1.606 + return; 1.607 + 1.608 + UnicodeString val(newValue, newValueLength); 1.609 + NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 1.610 + DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 1.611 + if (df != NULL) { 1.612 + switch(tag) { 1.613 + case UNUM_POSITIVE_PREFIX: 1.614 + df->setPositivePrefix(val); 1.615 + break; 1.616 + 1.617 + case UNUM_POSITIVE_SUFFIX: 1.618 + df->setPositiveSuffix(val); 1.619 + break; 1.620 + 1.621 + case UNUM_NEGATIVE_PREFIX: 1.622 + df->setNegativePrefix(val); 1.623 + break; 1.624 + 1.625 + case UNUM_NEGATIVE_SUFFIX: 1.626 + df->setNegativeSuffix(val); 1.627 + break; 1.628 + 1.629 + case UNUM_PADDING_CHARACTER: 1.630 + df->setPadCharacter(val); 1.631 + break; 1.632 + 1.633 + case UNUM_CURRENCY_CODE: 1.634 + df->setCurrency(val.getTerminatedBuffer(), *status); 1.635 + break; 1.636 + 1.637 + default: 1.638 + *status = U_UNSUPPORTED_ERROR; 1.639 + break; 1.640 + } 1.641 + } else { 1.642 + RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf); 1.643 + U_ASSERT(rbnf != NULL); 1.644 + if (tag == UNUM_DEFAULT_RULESET) { 1.645 + rbnf->setDefaultRuleSet(val, *status); 1.646 + } else { 1.647 + *status = U_UNSUPPORTED_ERROR; 1.648 + } 1.649 + } 1.650 +} 1.651 + 1.652 +U_CAPI int32_t U_EXPORT2 1.653 +unum_toPattern( const UNumberFormat* fmt, 1.654 + UBool isPatternLocalized, 1.655 + UChar* result, 1.656 + int32_t resultLength, 1.657 + UErrorCode* status) 1.658 +{ 1.659 + if(U_FAILURE(*status)) 1.660 + return -1; 1.661 + 1.662 + UnicodeString pat; 1.663 + if(!(result==NULL && resultLength==0)) { 1.664 + // NULL destination for pure preflighting: empty dummy string 1.665 + // otherwise, alias the destination buffer 1.666 + pat.setTo(result, 0, resultLength); 1.667 + } 1.668 + 1.669 + const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 1.670 + const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 1.671 + if (df != NULL) { 1.672 + if(isPatternLocalized) 1.673 + df->toLocalizedPattern(pat); 1.674 + else 1.675 + df->toPattern(pat); 1.676 + } else { 1.677 + const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 1.678 + U_ASSERT(rbnf != NULL); 1.679 + pat = rbnf->getRules(); 1.680 + } 1.681 + return pat.extract(result, resultLength, *status); 1.682 +} 1.683 + 1.684 +U_CAPI int32_t U_EXPORT2 1.685 +unum_getSymbol(const UNumberFormat *fmt, 1.686 + UNumberFormatSymbol symbol, 1.687 + UChar *buffer, 1.688 + int32_t size, 1.689 + UErrorCode *status) 1.690 +{ 1.691 + if(status==NULL || U_FAILURE(*status)) { 1.692 + return 0; 1.693 + } 1.694 + if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { 1.695 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.696 + return 0; 1.697 + } 1.698 + const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt); 1.699 + const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf); 1.700 + if (dcf == NULL) { 1.701 + *status = U_UNSUPPORTED_ERROR; 1.702 + return 0; 1.703 + } 1.704 + 1.705 + return dcf-> 1.706 + getDecimalFormatSymbols()-> 1.707 + getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol). 1.708 + extract(buffer, size, *status); 1.709 +} 1.710 + 1.711 +U_CAPI void U_EXPORT2 1.712 +unum_setSymbol(UNumberFormat *fmt, 1.713 + UNumberFormatSymbol symbol, 1.714 + const UChar *value, 1.715 + int32_t length, 1.716 + UErrorCode *status) 1.717 +{ 1.718 + if(status==NULL || U_FAILURE(*status)) { 1.719 + return; 1.720 + } 1.721 + if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) { 1.722 + *status=U_ILLEGAL_ARGUMENT_ERROR; 1.723 + return; 1.724 + } 1.725 + NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt); 1.726 + DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf); 1.727 + if (dcf == NULL) { 1.728 + *status = U_UNSUPPORTED_ERROR; 1.729 + return; 1.730 + } 1.731 + 1.732 + DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); 1.733 + symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, 1.734 + UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ 1.735 + dcf->setDecimalFormatSymbols(symbols); 1.736 +} 1.737 + 1.738 +U_CAPI void U_EXPORT2 1.739 +unum_applyPattern( UNumberFormat *fmt, 1.740 + UBool localized, 1.741 + const UChar *pattern, 1.742 + int32_t patternLength, 1.743 + UParseError *parseError, 1.744 + UErrorCode* status) 1.745 +{ 1.746 + UErrorCode tStatus = U_ZERO_ERROR; 1.747 + UParseError tParseError; 1.748 + 1.749 + if(parseError == NULL){ 1.750 + parseError = &tParseError; 1.751 + } 1.752 + 1.753 + if(status==NULL){ 1.754 + status = &tStatus; 1.755 + } 1.756 + 1.757 + int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength); 1.758 + const UnicodeString pat((UChar*)pattern, len, len); 1.759 + 1.760 + // Verify if the object passed is a DecimalFormat object 1.761 + NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 1.762 + DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 1.763 + if (df != NULL) { 1.764 + if(localized) { 1.765 + df->applyLocalizedPattern(pat,*parseError, *status); 1.766 + } else { 1.767 + df->applyPattern(pat,*parseError, *status); 1.768 + } 1.769 + } else { 1.770 + *status = U_UNSUPPORTED_ERROR; 1.771 + return; 1.772 + } 1.773 +} 1.774 + 1.775 +U_CAPI const char* U_EXPORT2 1.776 +unum_getLocaleByType(const UNumberFormat *fmt, 1.777 + ULocDataLocaleType type, 1.778 + UErrorCode* status) 1.779 +{ 1.780 + if (fmt == NULL) { 1.781 + if (U_SUCCESS(*status)) { 1.782 + *status = U_ILLEGAL_ARGUMENT_ERROR; 1.783 + } 1.784 + return NULL; 1.785 + } 1.786 + return ((const Format*)fmt)->getLocaleID(type, *status); 1.787 +} 1.788 + 1.789 +U_INTERNAL UFormattable * U_EXPORT2 1.790 +unum_parseToUFormattable(const UNumberFormat* fmt, 1.791 + UFormattable *result, 1.792 + const UChar* text, 1.793 + int32_t textLength, 1.794 + int32_t* parsePos, /* 0 = start */ 1.795 + UErrorCode* status) { 1.796 + UFormattable *newFormattable = NULL; 1.797 + if (U_FAILURE(*status)) return result; 1.798 + if (fmt == NULL || (text==NULL && textLength!=0)) { 1.799 + *status = U_ILLEGAL_ARGUMENT_ERROR; 1.800 + return result; 1.801 + } 1.802 + if (result == NULL) { // allocate if not allocated. 1.803 + newFormattable = result = ufmt_open(status); 1.804 + } 1.805 + parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); 1.806 + if (U_FAILURE(*status) && newFormattable != NULL) { 1.807 + ufmt_close(newFormattable); 1.808 + result = NULL; // deallocate if there was a parse error 1.809 + } 1.810 + return result; 1.811 +} 1.812 + 1.813 +U_INTERNAL int32_t U_EXPORT2 1.814 +unum_formatUFormattable(const UNumberFormat* fmt, 1.815 + const UFormattable *number, 1.816 + UChar *result, 1.817 + int32_t resultLength, 1.818 + UFieldPosition *pos, /* ignored if 0 */ 1.819 + UErrorCode *status) { 1.820 + if (U_FAILURE(*status)) { 1.821 + return 0; 1.822 + } 1.823 + if (fmt == NULL || number==NULL || 1.824 + (result==NULL ? resultLength!=0 : resultLength<0)) { 1.825 + *status = U_ILLEGAL_ARGUMENT_ERROR; 1.826 + return 0; 1.827 + } 1.828 + UnicodeString res(result, 0, resultLength); 1.829 + 1.830 + FieldPosition fp; 1.831 + 1.832 + if(pos != 0) 1.833 + fp.setField(pos->field); 1.834 + 1.835 + ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); 1.836 + 1.837 + if(pos != 0) { 1.838 + pos->beginIndex = fp.getBeginIndex(); 1.839 + pos->endIndex = fp.getEndIndex(); 1.840 + } 1.841 + 1.842 + return res.extract(result, resultLength, *status); 1.843 +} 1.844 + 1.845 +#endif /* #if !UCONFIG_NO_FORMATTING */