1 // Copyright (C) 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 251 U_CAPI int32_t U_EXPORT2 252 unum_formatDecimal(const UNumberFormat* fmt, 253 const char * number, 254 int32_t length, 255 UChar* result, 256 int32_t resultLength, 257 UFieldPosition *pos, /* 0 if ignore */ 258 UErrorCode* status) { 259 260 if(U_FAILURE(*status)) { 261 return -1; 262 } 263 if ((result == NULL && resultLength != 0) || resultLength < 0) { 264 *status = U_ILLEGAL_ARGUMENT_ERROR; 265 return -1; 266 } 267 268 FieldPosition fp; 269 if(pos != 0) { 270 fp.setField(pos->field); 271 } 272 273 if (length < 0) { 274 length = uprv_strlen(number); 275 } 276 StringPiece numSP(number, length); 277 Formattable numFmtbl(numSP, *status); 278 279 UnicodeString resultStr; 280 if (resultLength > 0) { 281 // Alias the destination buffer. 282 resultStr.setTo(result, 0, resultLength); 283 } 284 ((const NumberFormat*)fmt)->format(numFmtbl, resultStr, fp, *status); 285 if(pos != 0) { 286 pos->beginIndex = fp.getBeginIndex(); 287 pos->endIndex = fp.getEndIndex(); 288 } 289 return resultStr.extract(result, resultLength, *status); 290 } 291 292 293 294 295 U_CAPI int32_t U_EXPORT2 296 unum_formatDoubleCurrency(const UNumberFormat* fmt, 297 double number, 298 UChar* currency, 299 UChar* result, 300 int32_t resultLength, 301 UFieldPosition* pos, /* ignored if 0 */ 302 UErrorCode* status) { 303 if (U_FAILURE(*status)) return -1; 304 305 UnicodeString res; 306 if (!(result==NULL && resultLength==0)) { 307 // NULL destination for pure preflighting: empty dummy string 308 // otherwise, alias the destination buffer 309 res.setTo(result, 0, resultLength); 310 } 311 312 FieldPosition fp; 313 if (pos != 0) { 314 fp.setField(pos->field); 315 } 316 CurrencyAmount *tempCurrAmnt = new CurrencyAmount(number, currency, *status); 317 // Check for null pointer. 318 if (tempCurrAmnt == NULL) { 319 *status = U_MEMORY_ALLOCATION_ERROR; 320 return -1; 321 } 322 Formattable n(tempCurrAmnt); 323 ((const NumberFormat*)fmt)->format(n, res, fp, *status); 324 325 if (pos != 0) { 326 pos->beginIndex = fp.getBeginIndex(); 327 pos->endIndex = fp.getEndIndex(); 328 } 329 330 return res.extract(result, resultLength, *status); 331 } 332 333 static void 334 parseRes(Formattable& res, 335 const UNumberFormat* fmt, 336 const UChar* text, 337 int32_t textLength, 338 int32_t *parsePos /* 0 = start */, 339 UErrorCode *status) 340 { 341 if(U_FAILURE(*status)) 342 return; 343 344 const UnicodeString src((UBool)(textLength == -1), text, textLength); 345 ParsePosition pp; 346 347 if(parsePos != 0) 348 pp.setIndex(*parsePos); 349 350 ((const NumberFormat*)fmt)->parse(src, res, pp); 351 352 if(pp.getErrorIndex() != -1) { 353 *status = U_PARSE_ERROR; 354 if(parsePos != 0) { 355 *parsePos = pp.getErrorIndex(); 356 } 357 } else if(parsePos != 0) { 358 *parsePos = pp.getIndex(); 359 } 360 } 361 362 U_CAPI int32_t U_EXPORT2 363 unum_parse( 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, status); 371 return res.getLong(*status); 372 } 373 374 U_CAPI int64_t U_EXPORT2 375 unum_parseInt64( 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, status); 383 return res.getInt64(*status); 384 } 385 386 U_CAPI double U_EXPORT2 387 unum_parseDouble( const UNumberFormat* fmt, 388 const UChar* text, 389 int32_t textLength, 390 int32_t *parsePos /* 0 = start */, 391 UErrorCode *status) 392 { 393 Formattable res; 394 parseRes(res, fmt, text, textLength, parsePos, status); 395 return res.getDouble(*status); 396 } 397 398 U_CAPI int32_t U_EXPORT2 399 unum_parseDecimal(const UNumberFormat* fmt, 400 const UChar* text, 401 int32_t textLength, 402 int32_t *parsePos /* 0 = start */, 403 char *outBuf, 404 int32_t outBufLength, 405 UErrorCode *status) 406 { 407 if (U_FAILURE(*status)) { 408 return -1; 409 } 410 if ((outBuf == NULL && outBufLength != 0) || outBufLength < 0) { 411 *status = U_ILLEGAL_ARGUMENT_ERROR; 412 return -1; 413 } 414 Formattable res; 415 parseRes(res, fmt, text, textLength, parsePos, status); 416 StringPiece sp = res.getDecimalNumber(*status); 417 if (U_FAILURE(*status)) { 418 return -1; 419 } else if (sp.size() > outBufLength) { 420 *status = U_BUFFER_OVERFLOW_ERROR; 421 } else if (sp.size() == outBufLength) { 422 uprv_strncpy(outBuf, sp.data(), sp.size()); 423 *status = U_STRING_NOT_TERMINATED_WARNING; 424 } else { 425 U_ASSERT(outBufLength > 0); 426 uprv_strcpy(outBuf, sp.data()); 427 } 428 return sp.size(); 429 } 430 431 U_CAPI double U_EXPORT2 432 unum_parseDoubleCurrency(const UNumberFormat* fmt, 433 const UChar* text, 434 int32_t textLength, 435 int32_t* parsePos, /* 0 = start */ 436 UChar* currency, 437 UErrorCode* status) { 438 double doubleVal = 0.0; 439 currency[0] = 0; 440 if (U_FAILURE(*status)) { 441 return doubleVal; 442 } 443 const UnicodeString src((UBool)(textLength == -1), text, textLength); 444 ParsePosition pp; 445 if (parsePos != NULL) { 446 pp.setIndex(*parsePos); 447 } 448 *status = U_PARSE_ERROR; // assume failure, reset if succeed 449 LocalPointer<CurrencyAmount> currAmt(((const NumberFormat*)fmt)->parseCurrency(src, pp)); 450 if (pp.getErrorIndex() != -1) { 451 if (parsePos != NULL) { 452 *parsePos = pp.getErrorIndex(); 453 } 454 } else { 455 if (parsePos != NULL) { 456 *parsePos = pp.getIndex(); 457 } 458 if (pp.getIndex() > 0) { 459 *status = U_ZERO_ERROR; 460 u_strcpy(currency, currAmt->getISOCurrency()); 461 doubleVal = currAmt->getNumber().getDouble(*status); 462 } 463 } 464 return doubleVal; 465 } 466 467 U_CAPI const char* U_EXPORT2 468 unum_getAvailable(int32_t index) 469 { 470 return uloc_getAvailable(index); 471 } 472 473 U_CAPI int32_t U_EXPORT2 474 unum_countAvailable() 475 { 476 return uloc_countAvailable(); 477 } 478 479 U_CAPI int32_t U_EXPORT2 480 unum_getAttribute(const UNumberFormat* fmt, 481 UNumberFormatAttribute attr) 482 { 483 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 484 if ( attr == UNUM_LENIENT_PARSE ) { 485 // Supported for all subclasses 486 return nf->isLenient(); 487 } 488 489 // The remaining attributea are only supported for DecimalFormat 490 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 491 if (df != NULL) { 492 UErrorCode ignoredStatus = U_ZERO_ERROR; 493 return df->getAttribute( attr, ignoredStatus ); 494 } 495 496 return -1; 497 } 498 499 U_CAPI void U_EXPORT2 500 unum_setAttribute( UNumberFormat* fmt, 501 UNumberFormatAttribute attr, 502 int32_t newValue) 503 { 504 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 505 if ( attr == UNUM_LENIENT_PARSE ) { 506 // Supported for all subclasses 507 // keep this here as the class may not be a DecimalFormat 508 return nf->setLenient(newValue != 0); 509 } 510 // The remaining attributea are only supported for DecimalFormat 511 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 512 if (df != NULL) { 513 UErrorCode ignoredStatus = U_ZERO_ERROR; 514 df->setAttribute(attr, newValue, ignoredStatus); 515 } 516 } 517 518 U_CAPI double U_EXPORT2 519 unum_getDoubleAttribute(const UNumberFormat* fmt, 520 UNumberFormatAttribute attr) 521 { 522 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 523 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 524 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { 525 return df->getRoundingIncrement(); 526 } else { 527 return -1.0; 528 } 529 } 530 531 U_CAPI void U_EXPORT2 532 unum_setDoubleAttribute( UNumberFormat* fmt, 533 UNumberFormatAttribute attr, 534 double newValue) 535 { 536 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 537 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 538 if (df != NULL && attr == UNUM_ROUNDING_INCREMENT) { 539 df->setRoundingIncrement(newValue); 540 } 541 } 542 543 U_CAPI int32_t U_EXPORT2 544 unum_getTextAttribute(const UNumberFormat* fmt, 545 UNumberFormatTextAttribute tag, 546 UChar* result, 547 int32_t resultLength, 548 UErrorCode* status) 549 { 550 if(U_FAILURE(*status)) 551 return -1; 552 553 UnicodeString res; 554 if(!(result==NULL && resultLength==0)) { 555 // NULL destination for pure preflighting: empty dummy string 556 // otherwise, alias the destination buffer 557 res.setTo(result, 0, resultLength); 558 } 559 560 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 561 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 562 if (df != NULL) { 563 switch(tag) { 564 case UNUM_POSITIVE_PREFIX: 565 df->getPositivePrefix(res); 566 break; 567 568 case UNUM_POSITIVE_SUFFIX: 569 df->getPositiveSuffix(res); 570 break; 571 572 case UNUM_NEGATIVE_PREFIX: 573 df->getNegativePrefix(res); 574 break; 575 576 case UNUM_NEGATIVE_SUFFIX: 577 df->getNegativeSuffix(res); 578 break; 579 580 case UNUM_PADDING_CHARACTER: 581 res = df->getPadCharacterString(); 582 break; 583 584 case UNUM_CURRENCY_CODE: 585 res = UnicodeString(df->getCurrency()); 586 break; 587 588 default: 589 *status = U_UNSUPPORTED_ERROR; 590 return -1; 591 } 592 } else { 593 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 594 U_ASSERT(rbnf != NULL); 595 if (tag == UNUM_DEFAULT_RULESET) { 596 res = rbnf->getDefaultRuleSetName(); 597 } else if (tag == UNUM_PUBLIC_RULESETS) { 598 int32_t count = rbnf->getNumberOfRuleSetNames(); 599 for (int i = 0; i < count; ++i) { 600 res += rbnf->getRuleSetName(i); 601 res += (UChar)0x003b; // semicolon 602 } 603 } else { 604 *status = U_UNSUPPORTED_ERROR; 605 return -1; 606 } 607 } 608 609 return res.extract(result, resultLength, *status); 610 } 611 612 U_CAPI void U_EXPORT2 613 unum_setTextAttribute( UNumberFormat* fmt, 614 UNumberFormatTextAttribute tag, 615 const UChar* newValue, 616 int32_t newValueLength, 617 UErrorCode *status) 618 { 619 if(U_FAILURE(*status)) 620 return; 621 622 UnicodeString val(newValue, newValueLength); 623 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 624 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 625 if (df != NULL) { 626 switch(tag) { 627 case UNUM_POSITIVE_PREFIX: 628 df->setPositivePrefix(val); 629 break; 630 631 case UNUM_POSITIVE_SUFFIX: 632 df->setPositiveSuffix(val); 633 break; 634 635 case UNUM_NEGATIVE_PREFIX: 636 df->setNegativePrefix(val); 637 break; 638 639 case UNUM_NEGATIVE_SUFFIX: 640 df->setNegativeSuffix(val); 641 break; 642 643 case UNUM_PADDING_CHARACTER: 644 df->setPadCharacter(val); 645 break; 646 647 case UNUM_CURRENCY_CODE: 648 df->setCurrency(val.getTerminatedBuffer(), *status); 649 break; 650 651 default: 652 *status = U_UNSUPPORTED_ERROR; 653 break; 654 } 655 } else { 656 RuleBasedNumberFormat* rbnf = dynamic_cast<RuleBasedNumberFormat*>(nf); 657 U_ASSERT(rbnf != NULL); 658 if (tag == UNUM_DEFAULT_RULESET) { 659 rbnf->setDefaultRuleSet(val, *status); 660 } else { 661 *status = U_UNSUPPORTED_ERROR; 662 } 663 } 664 } 665 666 U_CAPI int32_t U_EXPORT2 667 unum_toPattern( const UNumberFormat* fmt, 668 UBool isPatternLocalized, 669 UChar* result, 670 int32_t resultLength, 671 UErrorCode* status) 672 { 673 if(U_FAILURE(*status)) 674 return -1; 675 676 UnicodeString pat; 677 if(!(result==NULL && resultLength==0)) { 678 // NULL destination for pure preflighting: empty dummy string 679 // otherwise, alias the destination buffer 680 pat.setTo(result, 0, resultLength); 681 } 682 683 const NumberFormat* nf = reinterpret_cast<const NumberFormat*>(fmt); 684 const DecimalFormat* df = dynamic_cast<const DecimalFormat*>(nf); 685 if (df != NULL) { 686 if(isPatternLocalized) 687 df->toLocalizedPattern(pat); 688 else 689 df->toPattern(pat); 690 } else { 691 const RuleBasedNumberFormat* rbnf = dynamic_cast<const RuleBasedNumberFormat*>(nf); 692 U_ASSERT(rbnf != NULL); 693 pat = rbnf->getRules(); 694 } 695 return pat.extract(result, resultLength, *status); 696 } 697 698 U_CAPI int32_t U_EXPORT2 699 unum_getSymbol(const UNumberFormat *fmt, 700 UNumberFormatSymbol symbol, 701 UChar *buffer, 702 int32_t size, 703 UErrorCode *status) 704 { 705 if(status==NULL || U_FAILURE(*status)) { 706 return 0; 707 } 708 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT) { 709 *status=U_ILLEGAL_ARGUMENT_ERROR; 710 return 0; 711 } 712 const NumberFormat *nf = reinterpret_cast<const NumberFormat *>(fmt); 713 const DecimalFormat *dcf = dynamic_cast<const DecimalFormat *>(nf); 714 if (dcf == NULL) { 715 *status = U_UNSUPPORTED_ERROR; 716 return 0; 717 } 718 719 return dcf-> 720 getDecimalFormatSymbols()-> 721 getConstSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol). 722 extract(buffer, size, *status); 723 } 724 725 U_CAPI void U_EXPORT2 726 unum_setSymbol(UNumberFormat *fmt, 727 UNumberFormatSymbol symbol, 728 const UChar *value, 729 int32_t length, 730 UErrorCode *status) 731 { 732 if(status==NULL || U_FAILURE(*status)) { 733 return; 734 } 735 if(fmt==NULL || symbol< 0 || symbol>=UNUM_FORMAT_SYMBOL_COUNT || value==NULL || length<-1) { 736 *status=U_ILLEGAL_ARGUMENT_ERROR; 737 return; 738 } 739 NumberFormat *nf = reinterpret_cast<NumberFormat *>(fmt); 740 DecimalFormat *dcf = dynamic_cast<DecimalFormat *>(nf); 741 if (dcf == NULL) { 742 *status = U_UNSUPPORTED_ERROR; 743 return; 744 } 745 746 DecimalFormatSymbols symbols(*dcf->getDecimalFormatSymbols()); 747 symbols.setSymbol((DecimalFormatSymbols::ENumberFormatSymbol)symbol, 748 UnicodeString(value, length)); /* UnicodeString can handle the case when length = -1. */ 749 dcf->setDecimalFormatSymbols(symbols); 750 } 751 752 U_CAPI void U_EXPORT2 753 unum_applyPattern( UNumberFormat *fmt, 754 UBool localized, 755 const UChar *pattern, 756 int32_t patternLength, 757 UParseError *parseError, 758 UErrorCode* status) 759 { 760 UErrorCode tStatus = U_ZERO_ERROR; 761 UParseError tParseError; 762 763 if(parseError == NULL){ 764 parseError = &tParseError; 765 } 766 767 if(status==NULL){ 768 status = &tStatus; 769 } 770 771 int32_t len = (patternLength == -1 ? u_strlen(pattern) : patternLength); 772 const UnicodeString pat((UChar*)pattern, len, len); 773 774 // Verify if the object passed is a DecimalFormat object 775 NumberFormat* nf = reinterpret_cast<NumberFormat*>(fmt); 776 DecimalFormat* df = dynamic_cast<DecimalFormat*>(nf); 777 if (df != NULL) { 778 if(localized) { 779 df->applyLocalizedPattern(pat,*parseError, *status); 780 } else { 781 df->applyPattern(pat,*parseError, *status); 782 } 783 } else { 784 *status = U_UNSUPPORTED_ERROR; 785 return; 786 } 787 } 788 789 U_CAPI const char* U_EXPORT2 790 unum_getLocaleByType(const UNumberFormat *fmt, 791 ULocDataLocaleType type, 792 UErrorCode* status) 793 { 794 if (fmt == NULL) { 795 if (U_SUCCESS(*status)) { 796 *status = U_ILLEGAL_ARGUMENT_ERROR; 797 } 798 return NULL; 799 } 800 return ((const Format*)fmt)->getLocaleID(type, *status); 801 } 802 803 U_CAPI void U_EXPORT2 804 unum_setContext(UNumberFormat* fmt, UDisplayContext value, UErrorCode* status) 805 { 806 if (U_FAILURE(*status)) { 807 return; 808 } 809 ((NumberFormat*)fmt)->setContext(value, *status); 810 return; 811 } 812 813 U_CAPI UDisplayContext U_EXPORT2 814 unum_getContext(const UNumberFormat *fmt, UDisplayContextType type, UErrorCode* status) 815 { 816 if (U_FAILURE(*status)) { 817 return (UDisplayContext)0; 818 } 819 return ((const NumberFormat*)fmt)->getContext(type, *status); 820 } 821 822 U_INTERNAL UFormattable * U_EXPORT2 823 unum_parseToUFormattable(const UNumberFormat* fmt, 824 UFormattable *result, 825 const UChar* text, 826 int32_t textLength, 827 int32_t* parsePos, /* 0 = start */ 828 UErrorCode* status) { 829 UFormattable *newFormattable = NULL; 830 if (U_FAILURE(*status)) return result; 831 if (fmt == NULL || (text==NULL && textLength!=0)) { 832 *status = U_ILLEGAL_ARGUMENT_ERROR; 833 return result; 834 } 835 if (result == NULL) { // allocate if not allocated. 836 newFormattable = result = ufmt_open(status); 837 } 838 parseRes(*(Formattable::fromUFormattable(result)), fmt, text, textLength, parsePos, status); 839 if (U_FAILURE(*status) && newFormattable != NULL) { 840 ufmt_close(newFormattable); 841 result = NULL; // deallocate if there was a parse error 842 } 843 return result; 844 } 845 846 U_INTERNAL int32_t U_EXPORT2 847 unum_formatUFormattable(const UNumberFormat* fmt, 848 const UFormattable *number, 849 UChar *result, 850 int32_t resultLength, 851 UFieldPosition *pos, /* ignored if 0 */ 852 UErrorCode *status) { 853 if (U_FAILURE(*status)) { 854 return 0; 855 } 856 if (fmt == NULL || number==NULL || 857 (result==NULL ? resultLength!=0 : resultLength<0)) { 858 *status = U_ILLEGAL_ARGUMENT_ERROR; 859 return 0; 860 } 861 UnicodeString res(result, 0, resultLength); 862 863 FieldPosition fp; 864 865 if(pos != 0) 866 fp.setField(pos->field); 867 868 ((const NumberFormat*)fmt)->format(*(Formattable::fromUFormattable(number)), res, fp, *status); 869 870 if(pos != 0) { 871 pos->beginIndex = fp.getBeginIndex(); 872 pos->endIndex = fp.getEndIndex(); 873 } 874 875 return res.extract(result, resultLength, *status); 876 } 877 878 #endif /* #if !UCONFIG_NO_FORMATTING */ 879