1/* 2******************************************************************************* 3* Copyright (C) 1996-2015, International Business Machines 4* Corporation and others. All Rights Reserved. 5******************************************************************************* 6* Modification History: 7* 8* Date Name Description 9* 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes 10******************************************************************************* 11*/ 12 13#include "unicode/utypes.h" 14 15#if !UCONFIG_NO_FORMATTING 16 17#include "unicode/unum.h" 18 19#include "unicode/uloc.h" 20#include "unicode/numfmt.h" 21#include "unicode/decimfmt.h" 22#include "unicode/rbnf.h" 23#include "unicode/compactdecimalformat.h" 24#include "unicode/ustring.h" 25#include "unicode/fmtable.h" 26#include "unicode/dcfmtsym.h" 27#include "unicode/curramt.h" 28#include "unicode/localpointer.h" 29#include "unicode/udisplaycontext.h" 30#include "uassert.h" 31#include "cpputils.h" 32#include "cstring.h" 33 34 35U_NAMESPACE_USE 36 37 38U_CAPI UNumberFormat* U_EXPORT2 39unum_open( UNumberFormatStyle style, 40 const UChar* pattern, 41 int32_t patternLength, 42 const char* locale, 43 UParseError* parseErr, 44 UErrorCode* status) { 45 if(U_FAILURE(*status)) { 46 return NULL; 47 } 48 49 NumberFormat *retVal = NULL; 50 51 switch(style) { 52 case UNUM_DECIMAL: 53 case UNUM_CURRENCY: 54 case UNUM_PERCENT: 55 case UNUM_SCIENTIFIC: 56 case UNUM_CURRENCY_ISO: 57 case UNUM_CURRENCY_PLURAL: 58 case UNUM_CURRENCY_ACCOUNTING: 59 case UNUM_CASH_CURRENCY: 60 case UNUM_CURRENCY_STANDARD: 61 retVal = NumberFormat::createInstance(Locale(locale), style, *status); 62 break; 63 64 case UNUM_PATTERN_DECIMAL: { 65 UParseError tErr; 66 /* UnicodeString can handle the case when patternLength = -1. */ 67 const UnicodeString pat(pattern, patternLength); 68 69 if(parseErr==NULL){ 70 parseErr = &tErr; 71 } 72 73 DecimalFormatSymbols *syms = new DecimalFormatSymbols(Locale(locale), *status); 74 if(syms == NULL) { 75 *status = U_MEMORY_ALLOCATION_ERROR; 76 return NULL; 77 } 78 if (U_FAILURE(*status)) { 79 delete syms; 80 return NULL; 81 } 82 83 retVal = new DecimalFormat(pat, syms, *parseErr, *status); 84 if(retVal == NULL) { 85 delete syms; 86 } 87 } break; 88 89#if U_HAVE_RBNF 90 case UNUM_PATTERN_RULEBASED: { 91 UParseError tErr; 92 /* UnicodeString can handle the case when patternLength = -1. */ 93 const UnicodeString pat(pattern, patternLength); 94 95 if(parseErr==NULL){ 96 parseErr = &tErr; 97 } 98 99 retVal = new RuleBasedNumberFormat(pat, Locale(locale), *parseErr, *status); 100 } break; 101 102 case UNUM_SPELLOUT: 103 retVal = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale(locale), *status); 104 break; 105 106 case UNUM_ORDINAL: 107 retVal = new RuleBasedNumberFormat(URBNF_ORDINAL, Locale(locale), *status); 108 break; 109 110 case UNUM_DURATION: 111 retVal = new RuleBasedNumberFormat(URBNF_DURATION, Locale(locale), *status); 112 break; 113 114 case UNUM_NUMBERING_SYSTEM: 115 retVal = new RuleBasedNumberFormat(URBNF_NUMBERING_SYSTEM, Locale(locale), *status); 116 break; 117#endif 118 119 case UNUM_DECIMAL_COMPACT_SHORT: 120 retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_SHORT, *status); 121 break; 122 123 case UNUM_DECIMAL_COMPACT_LONG: 124 retVal = CompactDecimalFormat::createInstance(Locale(locale), UNUM_LONG, *status); 125 break; 126 127 default: 128 *status = U_UNSUPPORTED_ERROR; 129 return NULL; 130 } 131 132 if(retVal == NULL && U_SUCCESS(*status)) { 133 *status = U_MEMORY_ALLOCATION_ERROR; 134 } 135 136 return reinterpret_cast<UNumberFormat *>(retVal); 137} 138 139U_CAPI void U_EXPORT2 140unum_close(UNumberFormat* fmt) 141{ 142 delete (NumberFormat*) fmt; 143} 144 145U_CAPI UNumberFormat* U_EXPORT2 146unum_clone(const UNumberFormat *fmt, 147 UErrorCode *status) 148{ 149 if(U_FAILURE(*status)) 150 return 0; 151 152 Format *res = 0; 153 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 154 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 155 if (df != NULL) { 156 res = df->clone(); 157 } else { 158 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 159 U_ASSERT(rbnf != NULL); 160 res = rbnf->clone(); 161 } 162 163 if(res == 0) { 164 *status = U_MEMORY_ALLOCATION_ERROR; 165 return 0; 166 } 167 168 return (UNumberFormat*) res; 169} 170 171U_CAPI int32_t U_EXPORT2 172unum_format( const UNumberFormat* fmt, 173 int32_t number, 174 UChar* result, 175 int32_t resultLength, 176 UFieldPosition *pos, 177 UErrorCode* status) 178{ 179 return unum_formatInt64(fmt, number, result, resultLength, pos, status); 180} 181 182U_CAPI int32_t U_EXPORT2 183unum_formatInt64(const UNumberFormat* fmt, 184 int64_t number, 185 UChar* result, 186 int32_t resultLength, 187 UFieldPosition *pos, 188 UErrorCode* status) 189{ 190 if(U_FAILURE(*status)) 191 return -1; 192 193 UnicodeString res; 194 if(!(result==NULL && resultLength==0)) { 195 // NULL destination for pure preflighting: empty dummy string 196 // otherwise, alias the destination buffer 197 res.setTo(result, 0, resultLength); 198 } 199 200 FieldPosition fp; 201 202 if(pos != 0) 203 fp.setField(pos->field); 204 205 ((const NumberFormat*)fmt)->format(number, res, fp, *status); 206 207 if(pos != 0) { 208 pos->beginIndex = fp.getBeginIndex(); 209 pos->endIndex = fp.getEndIndex(); 210 } 211 212 return res.extract(result, resultLength, *status); 213} 214 215U_CAPI int32_t U_EXPORT2 216unum_formatDouble( const UNumberFormat* fmt, 217 double number, 218 UChar* result, 219 int32_t resultLength, 220 UFieldPosition *pos, /* 0 if ignore */ 221 UErrorCode* status) 222{ 223 224 if(U_FAILURE(*status)) return -1; 225 226 UnicodeString res; 227 if(!(result==NULL && resultLength==0)) { 228 // NULL destination for pure preflighting: empty dummy string 229 // otherwise, alias the destination buffer 230 res.setTo(result, 0, resultLength); 231 } 232 233 FieldPosition fp; 234 235 if(pos != 0) 236 fp.setField(pos->field); 237 238 ((const NumberFormat*)fmt)->format(number, res, fp, *status); 239 240 if(pos != 0) { 241 pos->beginIndex = fp.getBeginIndex(); 242 pos->endIndex = fp.getEndIndex(); 243 } 244 245 return res.extract(result, resultLength, *status); 246} 247 248 249U_CAPI int32_t U_EXPORT2 250unum_formatDecimal(const UNumberFormat* fmt, 251 const char * number, 252 int32_t length, 253 UChar* result, 254 int32_t resultLength, 255 UFieldPosition *pos, /* 0 if ignore */ 256 UErrorCode* status) { 257 258 if(U_FAILURE(*status)) { 259 return -1; 260 } 261 if ((result == NULL && resultLength != 0) || resultLength < 0) { 262 *status = U_ILLEGAL_ARGUMENT_ERROR; 263 return -1; 264 } 265 266 FieldPosition fp; 267 if(pos != 0) { 268 fp.setField(pos->field); 269 } 270 271 if (length < 0) { 272 length = uprv_strlen(number); 273 } 274 StringPiece numSP(number, length); 275 Formattable numFmtbl(numSP, *status); 276 277 UnicodeString resultStr; 278 if (resultLength > 0) { 279 // Alias the destination buffer. 280 resultStr.setTo(result, 0, resultLength); 281 } 282 ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status); 283 if(pos != 0) { 284 pos->beginIndex = fp.getBeginIndex(); 285 pos->endIndex = fp.getEndIndex(); 286 } 287 return resultStr.extract(result, resultLength, *status); 288} 289 290 291 292 293U_CAPI int32_t U_EXPORT2 294unum_formatDoubleCurrency(const UNumberFormat* fmt, 295 double number, 296 UChar* currency, 297 UChar* result, 298 int32_t resultLength, 299 UFieldPosition* pos, /* ignored if 0 */ 300 UErrorCode* status) { 301 if (U_FAILURE(*status)) return -1; 302 303 UnicodeString res; 304 if (!(result==NULL && resultLength==0)) { 305 // NULL destination for pure preflighting: empty dummy string 306 // otherwise, alias the destination buffer 307 res.setTo(result, 0, resultLength); 308 } 309 310 FieldPosition fp; 311 if (pos != 0) { 312 fp.setField(pos->field); 313 } 314 CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status); 315 // Check for null pointer. 316 if (tempCurrAmnt == NULL) { 317 *status = U_MEMORY_ALLOCATION_ERROR; 318 return -1; 319 } 320 Formattable n(tempCurrAmnt); 321 ((const NumberFormat*)fmt)->format(n, res, fp, *status); 322 323 if (pos != 0) { 324 pos->beginIndex = fp.getBeginIndex(); 325 pos->endIndex = fp.getEndIndex(); 326 } 327 328 return res.extract(result, resultLength, *status); 329} 330 331static void 332parseRes(Formattable& res, 333 const UNumberFormat* fmt, 334 const UChar* text, 335 int32_t textLength, 336 int32_t *parsePos /* 0 = start */, 337 UErrorCode *status) 338{ 339 if(U_FAILURE(*status)) 340 return; 341 342 const UnicodeString src((UBool)(textLength == -1), text, textLength); 343 ParsePosition pp; 344 345 if(parsePos != 0) 346 pp.setIndex(*parsePos); 347 348 ((const NumberFormat*)fmt)->parse(src, res, pp); 349 350 if(pp.getErrorIndex() != -1) { 351 *status = U_PARSE_ERROR; 352 if(parsePos != 0) { 353 *parsePos = pp.getErrorIndex(); 354 } 355 } else if(parsePos != 0) { 356 *parsePos = pp.getIndex(); 357 } 358} 359 360U_CAPI int32_t U_EXPORT2 361unum_parse( const UNumberFormat* fmt, 362 const UChar* text, 363 int32_t textLength, 364 int32_t *parsePos /* 0 = start */, 365 UErrorCode *status) 366{ 367 Formattable res; 368 parseRes(res, fmt, text, textLength, parsePos, status); 369 return res.getLong(*status); 370} 371 372U_CAPI int64_t U_EXPORT2 373unum_parseInt64( const UNumberFormat* fmt, 374 const UChar* text, 375 int32_t textLength, 376 int32_t *parsePos /* 0 = start */, 377 UErrorCode *status) 378{ 379 Formattable res; 380 parseRes(res, fmt, text, textLength, parsePos, status); 381 return res.getInt64(*status); 382} 383 384U_CAPI double U_EXPORT2 385unum_parseDouble( const UNumberFormat* fmt, 386 const UChar* text, 387 int32_t textLength, 388 int32_t *parsePos /* 0 = start */, 389 UErrorCode *status) 390{ 391 Formattable res; 392 parseRes(res, fmt, text, textLength, parsePos, status); 393 return res.getDouble(*status); 394} 395 396U_CAPI int32_t U_EXPORT2 397unum_parseDecimal(const UNumberFormat* fmt, 398 const UChar* text, 399 int32_t textLength, 400 int32_t *parsePos /* 0 = start */, 401 char *outBuf, 402 int32_t outBufLength, 403 UErrorCode *status) 404{ 405 if (U_FAILURE(*status)) { 406 return -1; 407 } 408 if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) { 409 *status = U_ILLEGAL_ARGUMENT_ERROR; 410 return -1; 411 } 412 Formattable res; 413 parseRes(res, fmt, text, textLength, parsePos, status); 414 StringPiece sp = res.getDecimalNumber(*status); 415 if (U_FAILURE(*status)) { 416 return -1; 417 } else if (sp.size() > outBufLength) { 418 *status = U_BUFFER_OVERFLOW_ERROR; 419 } else if (sp.size() == outBufLength) { 420 uprv_strncpy(outBuf, sp.data(), sp.size()); 421 *status = U_STRING_NOT_TERMINATED_WARNING; 422 } else { 423 U_ASSERT(outBufLength > 0); 424 uprv_strcpy(outBuf, sp.data()); 425 } 426 return sp.size(); 427} 428 429U_CAPI double U_EXPORT2 430unum_parseDoubleCurrency(const UNumberFormat* fmt, 431 const UChar* text, 432 int32_t textLength, 433 int32_t* parsePos, /* 0 = start */ 434 UChar* currency, 435 UErrorCode* status) { 436 double doubleVal = 0.0; 437 currency[0] = 0; 438 if (U_FAILURE(*status)) { 439 return doubleVal; 440 } 441 const UnicodeString src((UBool)(textLength == -1), text, textLength); 442 ParsePosition pp; 443 if (parsePos != NULL) { 444 pp.setIndex(*parsePos); 445 } 446 *status = U_PARSE_ERROR; // assume failure, reset if succeed 447 LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp)); 448 if (pp.getErrorIndex() != -1) { 449 if (parsePos != NULL) { 450 *parsePos = pp.getErrorIndex(); 451 } 452 } else { 453 if (parsePos != NULL) { 454 *parsePos = pp.getIndex(); 455 } 456 if (pp.getIndex() > 0) { 457 *status = U_ZERO_ERROR; 458 u_strcpy(currency, currAmt->getISOCurrency()); 459 doubleVal = currAmt->getNumber().getDouble(*status); 460 } 461 } 462 return doubleVal; 463} 464 465U_CAPI const char* U_EXPORT2 466unum_getAvailable(int32_t index) 467{ 468 return uloc_getAvailable(index); 469} 470 471U_CAPI int32_t U_EXPORT2 472unum_countAvailable() 473{ 474 return uloc_countAvailable(); 475} 476 477U_CAPI int32_t U_EXPORT2 478unum_getAttribute(const UNumberFormat* fmt, 479 UNumberFormatAttribute attr) 480{ 481 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 482 if ( attr == UNUM_LENIENT_PARSE ) { 483 // Supported for all subclasses 484 return nf->isLenient(); 485 } 486 487 // The remaining attributea are only supported for DecimalFormat 488 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 489 if (df != NULL) { 490 UErrorCode ignoredStatus = U_ZERO_ERROR; 491 return df->getAttribute( attr, ignoredStatus ); 492 } 493 494 return -1; 495} 496 497U_CAPI void U_EXPORT2 498unum_setAttribute( UNumberFormat* fmt, 499 UNumberFormatAttribute attr, 500 int32_t newValue) 501{ 502 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 503 if ( attr == UNUM_LENIENT_PARSE ) { 504 // Supported for all subclasses 505 // keep this here as the class may not be a DecimalFormat 506 return nf->setLenient(newValue != 0); 507 } 508 // The remaining attributea are only supported for DecimalFormat 509 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 510 if (df != NULL) { 511 UErrorCode ignoredStatus = U_ZERO_ERROR; 512 df->setAttribute(attr, newValue, ignoredStatus); 513 } 514} 515 516U_CAPI double U_EXPORT2 517unum_getDoubleAttribute(const UNumberFormat* fmt, 518 UNumberFormatAttribute attr) 519{ 520 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 521 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 522 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { 523 return df->getRoundingIncrement(); 524 } else { 525 return -1.0; 526 } 527} 528 529U_CAPI void U_EXPORT2 530unum_setDoubleAttribute( UNumberFormat* fmt, 531 UNumberFormatAttribute attr, 532 double newValue) 533{ 534 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 535 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 536 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { 537 df->setRoundingIncrement(newValue); 538 } 539} 540 541U_CAPI int32_t U_EXPORT2 542unum_getTextAttribute(const UNumberFormat* fmt, 543 UNumberFormatTextAttribute tag, 544 UChar* result, 545 int32_t resultLength, 546 UErrorCode* status) 547{ 548 if(U_FAILURE(*status)) 549 return -1; 550 551 UnicodeString res; 552 if(!(result==NULL && resultLength==0)) { 553 // NULL destination for pure preflighting: empty dummy string 554 // otherwise, alias the destination buffer 555 res.setTo(result, 0, resultLength); 556 } 557 558 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 559 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 560 if (df != NULL) { 561 switch(tag) { 562 case UNUM_POSITIVE_PREFIX: 563 df->getPositivePrefix(res); 564 break; 565 566 case UNUM_POSITIVE_SUFFIX: 567 df->getPositiveSuffix(res); 568 break; 569 570 case UNUM_NEGATIVE_PREFIX: 571 df->getNegativePrefix(res); 572 break; 573 574 case UNUM_NEGATIVE_SUFFIX: 575 df->getNegativeSuffix(res); 576 break; 577 578 case UNUM_PADDING_CHARACTER: 579 res = df->getPadCharacterString(); 580 break; 581 582 case UNUM_CURRENCY_CODE: 583 res = UnicodeString(df->getCurrency()); 584 break; 585 586 default: 587 *status = U_UNSUPPORTED_ERROR; 588 return -1; 589 } 590 } else { 591 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 592 U_ASSERT(rbnf != NULL); 593 if (tag == UNUM_DEFAULT_RULESET) { 594 res = rbnf->getDefaultRuleSetName(); 595 } else if (tag == UNUM_PUBLIC_RULESETS) { 596 int32_t count = rbnf->getNumberOfRuleSetNames(); 597 for (int i = 0; i < count; ++i) { 598 res += rbnf->getRuleSetName(i); 599 res += (UChar)0x003b; // semicolon 600 } 601 } else { 602 *status = U_UNSUPPORTED_ERROR; 603 return -1; 604 } 605 } 606 607 return res.extract(result, resultLength, *status); 608} 609 610U_CAPI void U_EXPORT2 611unum_setTextAttribute( UNumberFormat* fmt, 612 UNumberFormatTextAttribute tag, 613 const UChar* newValue, 614 int32_t newValueLength, 615 UErrorCode *status) 616{ 617 if(U_FAILURE(*status)) 618 return; 619 620 UnicodeString val(newValue, newValueLength); 621 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 622 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 623 if (df != NULL) { 624 switch(tag) { 625 case UNUM_POSITIVE_PREFIX: 626 df->setPositivePrefix(val); 627 break; 628 629 case UNUM_POSITIVE_SUFFIX: 630 df->setPositiveSuffix(val); 631 break; 632 633 case UNUM_NEGATIVE_PREFIX: 634 df->setNegativePrefix(val); 635 break; 636 637 case UNUM_NEGATIVE_SUFFIX: 638 df->setNegativeSuffix(val); 639 break; 640 641 case UNUM_PADDING_CHARACTER: 642 df->setPadCharacter(val); 643 break; 644 645 case UNUM_CURRENCY_CODE: 646 df->setCurrency(val.getTerminatedBuffer(), *status); 647 break; 648 649 default: 650 *status = U_UNSUPPORTED_ERROR; 651 break; 652 } 653 } else { 654 RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf); 655 U_ASSERT(rbnf != NULL); 656 if (tag == UNUM_DEFAULT_RULESET) { 657 rbnf->setDefaultRuleSet(val, *status); 658 } else { 659 *status = U_UNSUPPORTED_ERROR; 660 } 661 } 662} 663 664U_CAPI int32_t U_EXPORT2 665unum_toPattern( const UNumberFormat* fmt, 666 UBool isPatternLocalized, 667 UChar* result, 668 int32_t resultLength, 669 UErrorCode* status) 670{ 671 if(U_FAILURE(*status)) 672 return -1; 673 674 UnicodeString pat; 675 if(!(result==NULL && resultLength==0)) { 676 // NULL destination for pure preflighting: empty dummy string 677 // otherwise, alias the destination buffer 678 pat.setTo(result, 0, resultLength); 679 } 680 681 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 682 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 683 if (df != NULL) { 684 if(isPatternLocalized) 685 df->toLocalizedPattern(pat); 686 else 687 df->toPattern(pat); 688 } else { 689 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 690 U_ASSERT(rbnf != NULL); 691 pat = rbnf->getRules(); 692 } 693 return pat.extract(result, resultLength, *status); 694} 695 696U_CAPI int32_t U_EXPORT2 697unum_getSymbol(const UNumberFormat *fmt, 698 UNumberFormatSymbol symbol, 699 UChar *buffer, 700 int32_t size, 701 UErrorCode *status) 702{ 703 if(status==NULL || U_FAILURE(*status)) { 704 return 0; 705 } 706 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { 707 *status=U_ILLEGAL_ARGUMENT_ERROR; 708 return 0; 709 } 710 const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt); 711 const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf); 712 if (dcf == NULL) { 713 *status = U_UNSUPPORTED_ERROR; 714 return 0; 715 } 716 717 return dcf-> 718 getDecimalFormatSymbols()-> 719 getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol). 720 extract(buffer, size, *status); 721} 722 723U_CAPI void U_EXPORT2 724unum_setSymbol(UNumberFormat *fmt, 725 UNumberFormatSymbol symbol, 726 const UChar *value, 727 int32_t length, 728 UErrorCode *status) 729{ 730 if(status==NULL || U_FAILURE(*status)) { 731 return; 732 } 733 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) { 734 *status=U_ILLEGAL_ARGUMENT_ERROR; 735 return; 736 } 737 NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt); 738 DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf); 739 if (dcf == NULL) { 740 *status = U_UNSUPPORTED_ERROR; 741 return; 742 } 743 744 DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); 745 symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, 746 UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ 747 dcf->setDecimalFormatSymbols(symbols); 748} 749 750U_CAPI void U_EXPORT2 751unum_applyPattern( UNumberFormat *fmt, 752 UBool localized, 753 const UChar *pattern, 754 int32_t patternLength, 755 UParseError *parseError, 756 UErrorCode* status) 757{ 758 UErrorCode tStatus = U_ZERO_ERROR; 759 UParseError tParseError; 760 761 if(parseError == NULL){ 762 parseError = &tParseError; 763 } 764 765 if(status==NULL){ 766 status = &tStatus; 767 } 768 769 int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength); 770 const UnicodeString pat((UChar*)pattern, len, len); 771 772 // Verify if the object passed is a DecimalFormat object 773 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 774 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 775 if (df != NULL) { 776 if(localized) { 777 df->applyLocalizedPattern(pat,*parseError, *status); 778 } else { 779 df->applyPattern(pat,*parseError, *status); 780 } 781 } else { 782 *status = U_UNSUPPORTED_ERROR; 783 return; 784 } 785} 786 787U_CAPI const char* U_EXPORT2 788unum_getLocaleByType(const UNumberFormat *fmt, 789 ULocDataLocaleType type, 790 UErrorCode* status) 791{ 792 if (fmt == NULL) { 793 if (U_SUCCESS(*status)) { 794 *status = U_ILLEGAL_ARGUMENT_ERROR; 795 } 796 return NULL; 797 } 798 return ((const Format*)fmt)->getLocaleID(type, *status); 799} 800 801U_CAPI void U_EXPORT2 802unum_setContext(UNumberFormat* fmt, UDisplayContext value, UErrorCode* status) 803{ 804 if (U_FAILURE(*status)) { 805 return; 806 } 807 ((NumberFormat*)fmt)->setContext(value, *status); 808 return; 809} 810 811U_CAPI UDisplayContext U_EXPORT2 812unum_getContext(const UNumberFormat *fmt, UDisplayContextType type, UErrorCode* status) 813{ 814 if (U_FAILURE(*status)) { 815 return (UDisplayContext)0; 816 } 817 return ((const NumberFormat*)fmt)->getContext(type, *status); 818} 819 820U_INTERNAL UFormattable * U_EXPORT2 821unum_parseToUFormattable(const UNumberFormat* fmt, 822 UFormattable *result, 823 const UChar* text, 824 int32_t textLength, 825 int32_t* parsePos, /* 0 = start */ 826 UErrorCode* status) { 827 UFormattable *newFormattable = NULL; 828 if (U_FAILURE(*status)) return result; 829 if (fmt == NULL || (text==NULL && textLength!=0)) { 830 *status = U_ILLEGAL_ARGUMENT_ERROR; 831 return result; 832 } 833 if (result == NULL) { // allocate if not allocated. 834 newFormattable = result = ufmt_open(status); 835 } 836 parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); 837 if (U_FAILURE(*status) && newFormattable != NULL) { 838 ufmt_close(newFormattable); 839 result = NULL; // deallocate if there was a parse error 840 } 841 return result; 842} 843 844U_INTERNAL int32_t U_EXPORT2 845unum_formatUFormattable(const UNumberFormat* fmt, 846 const UFormattable *number, 847 UChar *result, 848 int32_t resultLength, 849 UFieldPosition *pos, /* ignored if 0 */ 850 UErrorCode *status) { 851 if (U_FAILURE(*status)) { 852 return 0; 853 } 854 if (fmt == NULL || number==NULL || 855 (result==NULL ? resultLength!=0 : resultLength<0)) { 856 *status = U_ILLEGAL_ARGUMENT_ERROR; 857 return 0; 858 } 859 UnicodeString res(result, 0, resultLength); 860 861 FieldPosition fp; 862 863 if(pos != 0) 864 fp.setField(pos->field); 865 866 ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); 867 868 if(pos != 0) { 869 pos->beginIndex = fp.getBeginIndex(); 870 pos->endIndex = fp.getEndIndex(); 871 } 872 873 return res.extract(result, resultLength, *status); 874} 875 876#endif /* #if !UCONFIG_NO_FORMATTING */ 877