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