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