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