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