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