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