1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 1997-2015, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************** 6 * 7 * File MSGFMT.CPP 8 * 9 * Modification History: 10 * 11 * Date Name Description 12 * 02/19/97 aliu Converted from java. 13 * 03/20/97 helena Finished first cut of implementation. 14 * 04/10/97 aliu Made to work on AIX. Added stoi to replace wtoi. 15 * 06/11/97 helena Fixed addPattern to take the pattern correctly. 16 * 06/17/97 helena Fixed the getPattern to return the correct pattern. 17 * 07/09/97 helena Made ParsePosition into a class. 18 * 02/22/99 stephen Removed character literals for EBCDIC safety 19 * 11/01/09 kirtig Added SelectFormat 20 ********************************************************************/ 21 22 #include "unicode/utypes.h" 23 24 #if !UCONFIG_NO_FORMATTING 25 26 #include "unicode/appendable.h" 27 #include "unicode/choicfmt.h" 28 #include "unicode/datefmt.h" 29 #include "unicode/decimfmt.h" 30 #include "unicode/localpointer.h" 31 #include "unicode/msgfmt.h" 32 #include "unicode/plurfmt.h" 33 #include "unicode/rbnf.h" 34 #include "unicode/selfmt.h" 35 #include "unicode/smpdtfmt.h" 36 #include "unicode/umsg.h" 37 #include "unicode/ustring.h" 38 #include "cmemory.h" 39 #include "patternprops.h" 40 #include "messageimpl.h" 41 #include "msgfmt_impl.h" 42 #include "plurrule_impl.h" 43 #include "uassert.h" 44 #include "uelement.h" 45 #include "uhash.h" 46 #include "ustrfmt.h" 47 #include "util.h" 48 #include "uvector.h" 49 #include "visibledigits.h" 50 51 // ***************************************************************************** 52 // class MessageFormat 53 // ***************************************************************************** 54 55 #define SINGLE_QUOTE ((UChar)0x0027) 56 #define COMMA ((UChar)0x002C) 57 #define LEFT_CURLY_BRACE ((UChar)0x007B) 58 #define RIGHT_CURLY_BRACE ((UChar)0x007D) 59 60 //--------------------------------------- 61 // static data 62 63 static const UChar ID_NUMBER[] = { 64 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0 /* "number" */ 65 }; 66 static const UChar ID_DATE[] = { 67 0x64, 0x61, 0x74, 0x65, 0 /* "date" */ 68 }; 69 static const UChar ID_TIME[] = { 70 0x74, 0x69, 0x6D, 0x65, 0 /* "time" */ 71 }; 72 static const UChar ID_SPELLOUT[] = { 73 0x73, 0x70, 0x65, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0 /* "spellout" */ 74 }; 75 static const UChar ID_ORDINAL[] = { 76 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0 /* "ordinal" */ 77 }; 78 static const UChar ID_DURATION[] = { 79 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0 /* "duration" */ 80 }; 81 82 // MessageFormat Type List Number, Date, Time or Choice 83 static const UChar * const TYPE_IDS[] = { 84 ID_NUMBER, 85 ID_DATE, 86 ID_TIME, 87 ID_SPELLOUT, 88 ID_ORDINAL, 89 ID_DURATION, 90 NULL, 91 }; 92 93 static const UChar ID_EMPTY[] = { 94 0 /* empty string, used for default so that null can mark end of list */ 95 }; 96 static const UChar ID_CURRENCY[] = { 97 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x63, 0x79, 0 /* "currency" */ 98 }; 99 static const UChar ID_PERCENT[] = { 100 0x70, 0x65, 0x72, 0x63, 0x65, 0x6E, 0x74, 0 /* "percent" */ 101 }; 102 static const UChar ID_INTEGER[] = { 103 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0 /* "integer" */ 104 }; 105 106 // NumberFormat modifier list, default, currency, percent or integer 107 static const UChar * const NUMBER_STYLE_IDS[] = { 108 ID_EMPTY, 109 ID_CURRENCY, 110 ID_PERCENT, 111 ID_INTEGER, 112 NULL, 113 }; 114 115 static const UChar ID_SHORT[] = { 116 0x73, 0x68, 0x6F, 0x72, 0x74, 0 /* "short" */ 117 }; 118 static const UChar ID_MEDIUM[] = { 119 0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0 /* "medium" */ 120 }; 121 static const UChar ID_LONG[] = { 122 0x6C, 0x6F, 0x6E, 0x67, 0 /* "long" */ 123 }; 124 static const UChar ID_FULL[] = { 125 0x66, 0x75, 0x6C, 0x6C, 0 /* "full" */ 126 }; 127 128 // DateFormat modifier list, default, short, medium, long or full 129 static const UChar * const DATE_STYLE_IDS[] = { 130 ID_EMPTY, 131 ID_SHORT, 132 ID_MEDIUM, 133 ID_LONG, 134 ID_FULL, 135 NULL, 136 }; 137 138 static const icu::DateFormat::EStyle DATE_STYLES[] = { 139 icu::DateFormat::kDefault, 140 icu::DateFormat::kShort, 141 icu::DateFormat::kMedium, 142 icu::DateFormat::kLong, 143 icu::DateFormat::kFull, 144 }; 145 146 static const int32_t DEFAULT_INITIAL_CAPACITY = 10; 147 148 static const UChar NULL_STRING[] = { 149 0x6E, 0x75, 0x6C, 0x6C, 0 // "null" 150 }; 151 152 static const UChar OTHER_STRING[] = { 153 0x6F, 0x74, 0x68, 0x65, 0x72, 0 // "other" 154 }; 155 156 U_CDECL_BEGIN 157 static UBool U_CALLCONV equalFormatsForHash(const UHashTok key1, 158 const UHashTok key2) { 159 return icu::MessageFormat::equalFormats(key1.pointer, key2.pointer); 160 } 161 162 U_CDECL_END 163 164 U_NAMESPACE_BEGIN 165 166 // ------------------------------------- 167 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MessageFormat) 168 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FormatNameEnumeration) 169 170 //-------------------------------------------------------------------- 171 172 /** 173 * Convert an integer value to a string and append the result to 174 * the given UnicodeString. 175 */ 176 static UnicodeString& itos(int32_t i, UnicodeString& appendTo) { 177 UChar temp[16]; 178 uprv_itou(temp,16,i,10,0); // 10 == radix 179 appendTo.append(temp, -1); 180 return appendTo; 181 } 182 183 184 // AppendableWrapper: encapsulates the result of formatting, keeping track 185 // of the string and its length. 186 class AppendableWrapper : public UMemory { 187 public: 188 AppendableWrapper(Appendable& appendable) : app(appendable), len(0) { 189 } 190 void append(const UnicodeString& s) { 191 app.appendString(s.getBuffer(), s.length()); 192 len += s.length(); 193 } 194 void append(const UChar* s, const int32_t sLength) { 195 app.appendString(s, sLength); 196 len += sLength; 197 } 198 void append(const UnicodeString& s, int32_t start, int32_t length) { 199 append(s.tempSubString(start, length)); 200 } 201 void formatAndAppend(const Format* formatter, const Formattable& arg, UErrorCode& ec) { 202 UnicodeString s; 203 formatter->format(arg, s, ec); 204 if (U_SUCCESS(ec)) { 205 append(s); 206 } 207 } 208 void formatAndAppend(const Format* formatter, const Formattable& arg, 209 const UnicodeString &argString, UErrorCode& ec) { 210 if (!argString.isEmpty()) { 211 if (U_SUCCESS(ec)) { 212 append(argString); 213 } 214 } else { 215 formatAndAppend(formatter, arg, ec); 216 } 217 } 218 int32_t length() { 219 return len; 220 } 221 private: 222 Appendable& app; 223 int32_t len; 224 }; 225 226 227 // ------------------------------------- 228 // Creates a MessageFormat instance based on the pattern. 229 230 MessageFormat::MessageFormat(const UnicodeString& pattern, 231 UErrorCode& success) 232 : fLocale(Locale::getDefault()), // Uses the default locale 233 msgPattern(success), 234 formatAliases(NULL), 235 formatAliasesCapacity(0), 236 argTypes(NULL), 237 argTypeCount(0), 238 argTypeCapacity(0), 239 hasArgTypeConflicts(FALSE), 240 defaultNumberFormat(NULL), 241 defaultDateFormat(NULL), 242 cachedFormatters(NULL), 243 customFormatArgStarts(NULL), 244 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 245 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 246 { 247 setLocaleIDs(fLocale.getName(), fLocale.getName()); 248 applyPattern(pattern, success); 249 } 250 251 MessageFormat::MessageFormat(const UnicodeString& pattern, 252 const Locale& newLocale, 253 UErrorCode& success) 254 : fLocale(newLocale), 255 msgPattern(success), 256 formatAliases(NULL), 257 formatAliasesCapacity(0), 258 argTypes(NULL), 259 argTypeCount(0), 260 argTypeCapacity(0), 261 hasArgTypeConflicts(FALSE), 262 defaultNumberFormat(NULL), 263 defaultDateFormat(NULL), 264 cachedFormatters(NULL), 265 customFormatArgStarts(NULL), 266 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 267 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 268 { 269 setLocaleIDs(fLocale.getName(), fLocale.getName()); 270 applyPattern(pattern, success); 271 } 272 273 MessageFormat::MessageFormat(const UnicodeString& pattern, 274 const Locale& newLocale, 275 UParseError& parseError, 276 UErrorCode& success) 277 : fLocale(newLocale), 278 msgPattern(success), 279 formatAliases(NULL), 280 formatAliasesCapacity(0), 281 argTypes(NULL), 282 argTypeCount(0), 283 argTypeCapacity(0), 284 hasArgTypeConflicts(FALSE), 285 defaultNumberFormat(NULL), 286 defaultDateFormat(NULL), 287 cachedFormatters(NULL), 288 customFormatArgStarts(NULL), 289 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 290 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 291 { 292 setLocaleIDs(fLocale.getName(), fLocale.getName()); 293 applyPattern(pattern, parseError, success); 294 } 295 296 MessageFormat::MessageFormat(const MessageFormat& that) 297 : 298 Format(that), 299 fLocale(that.fLocale), 300 msgPattern(that.msgPattern), 301 formatAliases(NULL), 302 formatAliasesCapacity(0), 303 argTypes(NULL), 304 argTypeCount(0), 305 argTypeCapacity(0), 306 hasArgTypeConflicts(that.hasArgTypeConflicts), 307 defaultNumberFormat(NULL), 308 defaultDateFormat(NULL), 309 cachedFormatters(NULL), 310 customFormatArgStarts(NULL), 311 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 312 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 313 { 314 // This will take care of creating the hash tables (since they are NULL). 315 UErrorCode ec = U_ZERO_ERROR; 316 copyObjects(that, ec); 317 if (U_FAILURE(ec)) { 318 resetPattern(); 319 } 320 } 321 322 MessageFormat::~MessageFormat() 323 { 324 uhash_close(cachedFormatters); 325 uhash_close(customFormatArgStarts); 326 327 uprv_free(argTypes); 328 uprv_free(formatAliases); 329 delete defaultNumberFormat; 330 delete defaultDateFormat; 331 } 332 333 //-------------------------------------------------------------------- 334 // Variable-size array management 335 336 /** 337 * Allocate argTypes[] to at least the given capacity and return 338 * TRUE if successful. If not, leave argTypes[] unchanged. 339 * 340 * If argTypes is NULL, allocate it. If it is not NULL, enlarge it 341 * if necessary to be at least as large as specified. 342 */ 343 UBool MessageFormat::allocateArgTypes(int32_t capacity, UErrorCode& status) { 344 if (U_FAILURE(status)) { 345 return FALSE; 346 } 347 if (argTypeCapacity >= capacity) { 348 return TRUE; 349 } 350 if (capacity < DEFAULT_INITIAL_CAPACITY) { 351 capacity = DEFAULT_INITIAL_CAPACITY; 352 } else if (capacity < 2*argTypeCapacity) { 353 capacity = 2*argTypeCapacity; 354 } 355 Formattable::Type* a = (Formattable::Type*) 356 uprv_realloc(argTypes, sizeof(*argTypes) * capacity); 357 if (a == NULL) { 358 status = U_MEMORY_ALLOCATION_ERROR; 359 return FALSE; 360 } 361 argTypes = a; 362 argTypeCapacity = capacity; 363 return TRUE; 364 } 365 366 // ------------------------------------- 367 // assignment operator 368 369 const MessageFormat& 370 MessageFormat::operator=(const MessageFormat& that) 371 { 372 if (this != &that) { 373 // Calls the super class for assignment first. 374 Format::operator=(that); 375 376 setLocale(that.fLocale); 377 msgPattern = that.msgPattern; 378 hasArgTypeConflicts = that.hasArgTypeConflicts; 379 380 UErrorCode ec = U_ZERO_ERROR; 381 copyObjects(that, ec); 382 if (U_FAILURE(ec)) { 383 resetPattern(); 384 } 385 } 386 return *this; 387 } 388 389 UBool 390 MessageFormat::operator==(const Format& rhs) const 391 { 392 if (this == &rhs) return TRUE; 393 394 MessageFormat& that = (MessageFormat&)rhs; 395 396 // Check class ID before checking MessageFormat members 397 if (!Format::operator==(rhs) || 398 msgPattern != that.msgPattern || 399 fLocale != that.fLocale) { 400 return FALSE; 401 } 402 403 // Compare hashtables. 404 if ((customFormatArgStarts == NULL) != (that.customFormatArgStarts == NULL)) { 405 return FALSE; 406 } 407 if (customFormatArgStarts == NULL) { 408 return TRUE; 409 } 410 411 UErrorCode ec = U_ZERO_ERROR; 412 const int32_t count = uhash_count(customFormatArgStarts); 413 const int32_t rhs_count = uhash_count(that.customFormatArgStarts); 414 if (count != rhs_count) { 415 return FALSE; 416 } 417 int32_t idx = 0, rhs_idx = 0, pos = UHASH_FIRST, rhs_pos = UHASH_FIRST; 418 for (; idx < count && rhs_idx < rhs_count && U_SUCCESS(ec); ++idx, ++rhs_idx) { 419 const UHashElement* cur = uhash_nextElement(customFormatArgStarts, &pos); 420 const UHashElement* rhs_cur = uhash_nextElement(that.customFormatArgStarts, &rhs_pos); 421 if (cur->key.integer != rhs_cur->key.integer) { 422 return FALSE; 423 } 424 const Format* format = (const Format*)uhash_iget(cachedFormatters, cur->key.integer); 425 const Format* rhs_format = (const Format*)uhash_iget(that.cachedFormatters, rhs_cur->key.integer); 426 if (*format != *rhs_format) { 427 return FALSE; 428 } 429 } 430 return TRUE; 431 } 432 433 // ------------------------------------- 434 // Creates a copy of this MessageFormat, the caller owns the copy. 435 436 Format* 437 MessageFormat::clone() const 438 { 439 return new MessageFormat(*this); 440 } 441 442 // ------------------------------------- 443 // Sets the locale of this MessageFormat object to theLocale. 444 445 void 446 MessageFormat::setLocale(const Locale& theLocale) 447 { 448 if (fLocale != theLocale) { 449 delete defaultNumberFormat; 450 defaultNumberFormat = NULL; 451 delete defaultDateFormat; 452 defaultDateFormat = NULL; 453 fLocale = theLocale; 454 setLocaleIDs(fLocale.getName(), fLocale.getName()); 455 pluralProvider.reset(); 456 ordinalProvider.reset(); 457 } 458 } 459 460 // ------------------------------------- 461 // Gets the locale of this MessageFormat object. 462 463 const Locale& 464 MessageFormat::getLocale() const 465 { 466 return fLocale; 467 } 468 469 void 470 MessageFormat::applyPattern(const UnicodeString& newPattern, 471 UErrorCode& status) 472 { 473 UParseError parseError; 474 applyPattern(newPattern,parseError,status); 475 } 476 477 478 // ------------------------------------- 479 // Applies the new pattern and returns an error if the pattern 480 // is not correct. 481 void 482 MessageFormat::applyPattern(const UnicodeString& pattern, 483 UParseError& parseError, 484 UErrorCode& ec) 485 { 486 if(U_FAILURE(ec)) { 487 return; 488 } 489 msgPattern.parse(pattern, &parseError, ec); 490 cacheExplicitFormats(ec); 491 492 if (U_FAILURE(ec)) { 493 resetPattern(); 494 } 495 } 496 497 void MessageFormat::resetPattern() { 498 msgPattern.clear(); 499 uhash_close(cachedFormatters); 500 cachedFormatters = NULL; 501 uhash_close(customFormatArgStarts); 502 customFormatArgStarts = NULL; 503 argTypeCount = 0; 504 hasArgTypeConflicts = FALSE; 505 } 506 507 void 508 MessageFormat::applyPattern(const UnicodeString& pattern, 509 UMessagePatternApostropheMode aposMode, 510 UParseError* parseError, 511 UErrorCode& status) { 512 if (aposMode != msgPattern.getApostropheMode()) { 513 msgPattern.clearPatternAndSetApostropheMode(aposMode); 514 } 515 applyPattern(pattern, *parseError, status); 516 } 517 518 // ------------------------------------- 519 // Converts this MessageFormat instance to a pattern. 520 521 UnicodeString& 522 MessageFormat::toPattern(UnicodeString& appendTo) const { 523 if ((customFormatArgStarts != NULL && 0 != uhash_count(customFormatArgStarts)) || 524 0 == msgPattern.countParts() 525 ) { 526 appendTo.setToBogus(); 527 return appendTo; 528 } 529 return appendTo.append(msgPattern.getPatternString()); 530 } 531 532 int32_t MessageFormat::nextTopLevelArgStart(int32_t partIndex) const { 533 if (partIndex != 0) { 534 partIndex = msgPattern.getLimitPartIndex(partIndex); 535 } 536 for (;;) { 537 UMessagePatternPartType type = msgPattern.getPartType(++partIndex); 538 if (type == UMSGPAT_PART_TYPE_ARG_START) { 539 return partIndex; 540 } 541 if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) { 542 return -1; 543 } 544 } 545 } 546 547 void MessageFormat::setArgStartFormat(int32_t argStart, 548 Format* formatter, 549 UErrorCode& status) { 550 if (U_FAILURE(status)) { 551 delete formatter; 552 return; 553 } 554 if (cachedFormatters == NULL) { 555 cachedFormatters=uhash_open(uhash_hashLong, uhash_compareLong, 556 equalFormatsForHash, &status); 557 if (U_FAILURE(status)) { 558 delete formatter; 559 return; 560 } 561 uhash_setValueDeleter(cachedFormatters, uprv_deleteUObject); 562 } 563 if (formatter == NULL) { 564 formatter = new DummyFormat(); 565 } 566 uhash_iput(cachedFormatters, argStart, formatter, &status); 567 } 568 569 570 UBool MessageFormat::argNameMatches(int32_t partIndex, const UnicodeString& argName, int32_t argNumber) { 571 const MessagePattern::Part& part = msgPattern.getPart(partIndex); 572 return part.getType() == UMSGPAT_PART_TYPE_ARG_NAME ? 573 msgPattern.partSubstringMatches(part, argName) : 574 part.getValue() == argNumber; // ARG_NUMBER 575 } 576 577 // Sets a custom formatter for a MessagePattern ARG_START part index. 578 // "Custom" formatters are provided by the user via setFormat() or similar APIs. 579 void MessageFormat::setCustomArgStartFormat(int32_t argStart, 580 Format* formatter, 581 UErrorCode& status) { 582 setArgStartFormat(argStart, formatter, status); 583 if (customFormatArgStarts == NULL) { 584 customFormatArgStarts=uhash_open(uhash_hashLong, uhash_compareLong, 585 NULL, &status); 586 } 587 uhash_iputi(customFormatArgStarts, argStart, 1, &status); 588 } 589 590 Format* MessageFormat::getCachedFormatter(int32_t argumentNumber) const { 591 if (cachedFormatters == NULL) { 592 return NULL; 593 } 594 void* ptr = uhash_iget(cachedFormatters, argumentNumber); 595 if (ptr != NULL && dynamic_cast<DummyFormat*>((Format*)ptr) == NULL) { 596 return (Format*) ptr; 597 } else { 598 // Not cached, or a DummyFormat representing setFormat(NULL). 599 return NULL; 600 } 601 } 602 603 // ------------------------------------- 604 // Adopts the new formats array and updates the array count. 605 // This MessageFormat instance owns the new formats. 606 void 607 MessageFormat::adoptFormats(Format** newFormats, 608 int32_t count) { 609 if (newFormats == NULL || count < 0) { 610 return; 611 } 612 // Throw away any cached formatters. 613 if (cachedFormatters != NULL) { 614 uhash_removeAll(cachedFormatters); 615 } 616 if (customFormatArgStarts != NULL) { 617 uhash_removeAll(customFormatArgStarts); 618 } 619 620 int32_t formatNumber = 0; 621 UErrorCode status = U_ZERO_ERROR; 622 for (int32_t partIndex = 0; 623 formatNumber < count && U_SUCCESS(status) && 624 (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 625 setCustomArgStartFormat(partIndex, newFormats[formatNumber], status); 626 ++formatNumber; 627 } 628 // Delete those that didn't get used (if any). 629 for (; formatNumber < count; ++formatNumber) { 630 delete newFormats[formatNumber]; 631 } 632 633 } 634 635 // ------------------------------------- 636 // Sets the new formats array and updates the array count. 637 // This MessageFormat instance maks a copy of the new formats. 638 639 void 640 MessageFormat::setFormats(const Format** newFormats, 641 int32_t count) { 642 if (newFormats == NULL || count < 0) { 643 return; 644 } 645 // Throw away any cached formatters. 646 if (cachedFormatters != NULL) { 647 uhash_removeAll(cachedFormatters); 648 } 649 if (customFormatArgStarts != NULL) { 650 uhash_removeAll(customFormatArgStarts); 651 } 652 653 UErrorCode status = U_ZERO_ERROR; 654 int32_t formatNumber = 0; 655 for (int32_t partIndex = 0; 656 formatNumber < count && U_SUCCESS(status) && (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 657 Format* newFormat = NULL; 658 if (newFormats[formatNumber] != NULL) { 659 newFormat = newFormats[formatNumber]->clone(); 660 if (newFormat == NULL) { 661 status = U_MEMORY_ALLOCATION_ERROR; 662 } 663 } 664 setCustomArgStartFormat(partIndex, newFormat, status); 665 ++formatNumber; 666 } 667 if (U_FAILURE(status)) { 668 resetPattern(); 669 } 670 } 671 672 // ------------------------------------- 673 // Adopt a single format by format number. 674 // Do nothing if the format number is not less than the array count. 675 676 void 677 MessageFormat::adoptFormat(int32_t n, Format *newFormat) { 678 LocalPointer<Format> p(newFormat); 679 if (n >= 0) { 680 int32_t formatNumber = 0; 681 for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 682 if (n == formatNumber) { 683 UErrorCode status = U_ZERO_ERROR; 684 setCustomArgStartFormat(partIndex, p.orphan(), status); 685 return; 686 } 687 ++formatNumber; 688 } 689 } 690 } 691 692 // ------------------------------------- 693 // Adopt a single format by format name. 694 // Do nothing if there is no match of formatName. 695 void 696 MessageFormat::adoptFormat(const UnicodeString& formatName, 697 Format* formatToAdopt, 698 UErrorCode& status) { 699 LocalPointer<Format> p(formatToAdopt); 700 if (U_FAILURE(status)) { 701 return; 702 } 703 int32_t argNumber = MessagePattern::validateArgumentName(formatName); 704 if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) { 705 status = U_ILLEGAL_ARGUMENT_ERROR; 706 return; 707 } 708 for (int32_t partIndex = 0; 709 (partIndex = nextTopLevelArgStart(partIndex)) >= 0 && U_SUCCESS(status); 710 ) { 711 if (argNameMatches(partIndex + 1, formatName, argNumber)) { 712 Format* f; 713 if (p.isValid()) { 714 f = p.orphan(); 715 } else if (formatToAdopt == NULL) { 716 f = NULL; 717 } else { 718 f = formatToAdopt->clone(); 719 if (f == NULL) { 720 status = U_MEMORY_ALLOCATION_ERROR; 721 return; 722 } 723 } 724 setCustomArgStartFormat(partIndex, f, status); 725 } 726 } 727 } 728 729 // ------------------------------------- 730 // Set a single format. 731 // Do nothing if the variable is not less than the array count. 732 void 733 MessageFormat::setFormat(int32_t n, const Format& newFormat) { 734 735 if (n >= 0) { 736 int32_t formatNumber = 0; 737 for (int32_t partIndex = 0; 738 (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 739 if (n == formatNumber) { 740 Format* new_format = newFormat.clone(); 741 if (new_format) { 742 UErrorCode status = U_ZERO_ERROR; 743 setCustomArgStartFormat(partIndex, new_format, status); 744 } 745 return; 746 } 747 ++formatNumber; 748 } 749 } 750 } 751 752 // ------------------------------------- 753 // Get a single format by format name. 754 // Do nothing if the variable is not less than the array count. 755 Format * 756 MessageFormat::getFormat(const UnicodeString& formatName, UErrorCode& status) { 757 if (U_FAILURE(status) || cachedFormatters == NULL) return NULL; 758 759 int32_t argNumber = MessagePattern::validateArgumentName(formatName); 760 if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) { 761 status = U_ILLEGAL_ARGUMENT_ERROR; 762 return NULL; 763 } 764 for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 765 if (argNameMatches(partIndex + 1, formatName, argNumber)) { 766 return getCachedFormatter(partIndex); 767 } 768 } 769 return NULL; 770 } 771 772 // ------------------------------------- 773 // Set a single format by format name 774 // Do nothing if the variable is not less than the array count. 775 void 776 MessageFormat::setFormat(const UnicodeString& formatName, 777 const Format& newFormat, 778 UErrorCode& status) { 779 if (U_FAILURE(status)) return; 780 781 int32_t argNumber = MessagePattern::validateArgumentName(formatName); 782 if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) { 783 status = U_ILLEGAL_ARGUMENT_ERROR; 784 return; 785 } 786 for (int32_t partIndex = 0; 787 (partIndex = nextTopLevelArgStart(partIndex)) >= 0 && U_SUCCESS(status); 788 ) { 789 if (argNameMatches(partIndex + 1, formatName, argNumber)) { 790 Format* new_format = newFormat.clone(); 791 if (new_format == NULL) { 792 status = U_MEMORY_ALLOCATION_ERROR; 793 return; 794 } 795 setCustomArgStartFormat(partIndex, new_format, status); 796 } 797 } 798 } 799 800 // ------------------------------------- 801 // Gets the format array. 802 const Format** 803 MessageFormat::getFormats(int32_t& cnt) const 804 { 805 // This old API returns an array (which we hold) of Format* 806 // pointers. The array is valid up to the next call to any 807 // method on this object. We construct and resize an array 808 // on demand that contains aliases to the subformats[i].format 809 // pointers. 810 MessageFormat* t = const_cast<MessageFormat*> (this); 811 cnt = 0; 812 if (formatAliases == NULL) { 813 t->formatAliasesCapacity = (argTypeCount<10) ? 10 : argTypeCount; 814 Format** a = (Format**) 815 uprv_malloc(sizeof(Format*) * formatAliasesCapacity); 816 if (a == NULL) { 817 t->formatAliasesCapacity = 0; 818 return NULL; 819 } 820 t->formatAliases = a; 821 } else if (argTypeCount > formatAliasesCapacity) { 822 Format** a = (Format**) 823 uprv_realloc(formatAliases, sizeof(Format*) * argTypeCount); 824 if (a == NULL) { 825 t->formatAliasesCapacity = 0; 826 return NULL; 827 } 828 t->formatAliases = a; 829 t->formatAliasesCapacity = argTypeCount; 830 } 831 832 for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 833 t->formatAliases[cnt++] = getCachedFormatter(partIndex); 834 } 835 836 return (const Format**)formatAliases; 837 } 838 839 840 UnicodeString MessageFormat::getArgName(int32_t partIndex) { 841 const MessagePattern::Part& part = msgPattern.getPart(partIndex); 842 return msgPattern.getSubstring(part); 843 } 844 845 StringEnumeration* 846 MessageFormat::getFormatNames(UErrorCode& status) { 847 if (U_FAILURE(status)) return NULL; 848 849 UVector *fFormatNames = new UVector(status); 850 if (U_FAILURE(status)) { 851 status = U_MEMORY_ALLOCATION_ERROR; 852 return NULL; 853 } 854 fFormatNames->setDeleter(uprv_deleteUObject); 855 856 for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 857 fFormatNames->addElement(new UnicodeString(getArgName(partIndex + 1)), status); 858 } 859 860 StringEnumeration* nameEnumerator = new FormatNameEnumeration(fFormatNames, status); 861 return nameEnumerator; 862 } 863 864 // ------------------------------------- 865 // Formats the source Formattable array and copy into the result buffer. 866 // Ignore the FieldPosition result for error checking. 867 868 UnicodeString& 869 MessageFormat::format(const Formattable* source, 870 int32_t cnt, 871 UnicodeString& appendTo, 872 FieldPosition& ignore, 873 UErrorCode& success) const 874 { 875 return format(source, NULL, cnt, appendTo, &ignore, success); 876 } 877 878 // ------------------------------------- 879 // Internally creates a MessageFormat instance based on the 880 // pattern and formats the arguments Formattable array and 881 // copy into the appendTo buffer. 882 883 UnicodeString& 884 MessageFormat::format( const UnicodeString& pattern, 885 const Formattable* arguments, 886 int32_t cnt, 887 UnicodeString& appendTo, 888 UErrorCode& success) 889 { 890 MessageFormat temp(pattern, success); 891 return temp.format(arguments, NULL, cnt, appendTo, NULL, success); 892 } 893 894 // ------------------------------------- 895 // Formats the source Formattable object and copy into the 896 // appendTo buffer. The Formattable object must be an array 897 // of Formattable instances, returns error otherwise. 898 899 UnicodeString& 900 MessageFormat::format(const Formattable& source, 901 UnicodeString& appendTo, 902 FieldPosition& ignore, 903 UErrorCode& success) const 904 { 905 if (U_FAILURE(success)) 906 return appendTo; 907 if (source.getType() != Formattable::kArray) { 908 success = U_ILLEGAL_ARGUMENT_ERROR; 909 return appendTo; 910 } 911 int32_t cnt; 912 const Formattable* tmpPtr = source.getArray(cnt); 913 return format(tmpPtr, NULL, cnt, appendTo, &ignore, success); 914 } 915 916 UnicodeString& 917 MessageFormat::format(const UnicodeString* argumentNames, 918 const Formattable* arguments, 919 int32_t count, 920 UnicodeString& appendTo, 921 UErrorCode& success) const { 922 return format(arguments, argumentNames, count, appendTo, NULL, success); 923 } 924 925 // Does linear search to find the match for an ArgName. 926 const Formattable* MessageFormat::getArgFromListByName(const Formattable* arguments, 927 const UnicodeString *argumentNames, 928 int32_t cnt, UnicodeString& name) const { 929 for (int32_t i = 0; i < cnt; ++i) { 930 if (0 == argumentNames[i].compare(name)) { 931 return arguments + i; 932 } 933 } 934 return NULL; 935 } 936 937 938 UnicodeString& 939 MessageFormat::format(const Formattable* arguments, 940 const UnicodeString *argumentNames, 941 int32_t cnt, 942 UnicodeString& appendTo, 943 FieldPosition* pos, 944 UErrorCode& status) const { 945 if (U_FAILURE(status)) { 946 return appendTo; 947 } 948 949 UnicodeStringAppendable usapp(appendTo); 950 AppendableWrapper app(usapp); 951 format(0, NULL, arguments, argumentNames, cnt, app, pos, status); 952 return appendTo; 953 } 954 955 namespace { 956 957 /** 958 * Mutable input/output values for the PluralSelectorProvider. 959 * Separate so that it is possible to make MessageFormat Freezable. 960 */ 961 class PluralSelectorContext { 962 public: 963 PluralSelectorContext(int32_t start, const UnicodeString &name, 964 const Formattable &num, double off, UErrorCode &errorCode) 965 : startIndex(start), argName(name), offset(off), 966 numberArgIndex(-1), formatter(NULL), forReplaceNumber(FALSE) { 967 // number needs to be set even when select() is not called. 968 // Keep it as a Number/Formattable: 969 // For format() methods, and to preserve information (e.g., BigDecimal). 970 if(off == 0) { 971 number = num; 972 } else { 973 number = num.getDouble(errorCode) - off; 974 } 975 } 976 977 // Input values for plural selection with decimals. 978 int32_t startIndex; 979 const UnicodeString &argName; 980 /** argument number - plural offset */ 981 Formattable number; 982 double offset; 983 // Output values for plural selection with decimals. 984 /** -1 if REPLACE_NUMBER, 0 arg not found, >0 ARG_START index */ 985 int32_t numberArgIndex; 986 const Format *formatter; 987 /** formatted argument number - plural offset */ 988 UnicodeString numberString; 989 /** TRUE if number-offset was formatted with the stock number formatter */ 990 UBool forReplaceNumber; 991 }; 992 993 } // namespace 994 995 // if argumentNames is NULL, this means arguments is a numeric array. 996 // arguments can not be NULL. 997 // We use const void *plNumber rather than const PluralSelectorContext *pluralNumber 998 // so that we need not declare the PluralSelectorContext in the public header file. 999 void MessageFormat::format(int32_t msgStart, const void *plNumber, 1000 const Formattable* arguments, 1001 const UnicodeString *argumentNames, 1002 int32_t cnt, 1003 AppendableWrapper& appendTo, 1004 FieldPosition* ignore, 1005 UErrorCode& success) const { 1006 if (U_FAILURE(success)) { 1007 return; 1008 } 1009 1010 const UnicodeString& msgString = msgPattern.getPatternString(); 1011 int32_t prevIndex = msgPattern.getPart(msgStart).getLimit(); 1012 for (int32_t i = msgStart + 1; U_SUCCESS(success) ; ++i) { 1013 const MessagePattern::Part* part = &msgPattern.getPart(i); 1014 const UMessagePatternPartType type = part->getType(); 1015 int32_t index = part->getIndex(); 1016 appendTo.append(msgString, prevIndex, index - prevIndex); 1017 if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) { 1018 return; 1019 } 1020 prevIndex = part->getLimit(); 1021 if (type == UMSGPAT_PART_TYPE_REPLACE_NUMBER) { 1022 const PluralSelectorContext &pluralNumber = 1023 *static_cast<const PluralSelectorContext *>(plNumber); 1024 if(pluralNumber.forReplaceNumber) { 1025 // number-offset was already formatted. 1026 appendTo.formatAndAppend(pluralNumber.formatter, 1027 pluralNumber.number, pluralNumber.numberString, success); 1028 } else { 1029 const NumberFormat* nf = getDefaultNumberFormat(success); 1030 appendTo.formatAndAppend(nf, pluralNumber.number, success); 1031 } 1032 continue; 1033 } 1034 if (type != UMSGPAT_PART_TYPE_ARG_START) { 1035 continue; 1036 } 1037 int32_t argLimit = msgPattern.getLimitPartIndex(i); 1038 UMessagePatternArgType argType = part->getArgType(); 1039 part = &msgPattern.getPart(++i); 1040 const Formattable* arg; 1041 UBool noArg = FALSE; 1042 UnicodeString argName = msgPattern.getSubstring(*part); 1043 if (argumentNames == NULL) { 1044 int32_t argNumber = part->getValue(); // ARG_NUMBER 1045 if (0 <= argNumber && argNumber < cnt) { 1046 arg = arguments + argNumber; 1047 } else { 1048 arg = NULL; 1049 noArg = TRUE; 1050 } 1051 } else { 1052 arg = getArgFromListByName(arguments, argumentNames, cnt, argName); 1053 if (arg == NULL) { 1054 noArg = TRUE; 1055 } 1056 } 1057 ++i; 1058 int32_t prevDestLength = appendTo.length(); 1059 const Format* formatter = NULL; 1060 if (noArg) { 1061 appendTo.append( 1062 UnicodeString(LEFT_CURLY_BRACE).append(argName).append(RIGHT_CURLY_BRACE)); 1063 } else if (arg == NULL) { 1064 appendTo.append(NULL_STRING, 4); 1065 } else if(plNumber!=NULL && 1066 static_cast<const PluralSelectorContext *>(plNumber)->numberArgIndex==(i-2)) { 1067 const PluralSelectorContext &pluralNumber = 1068 *static_cast<const PluralSelectorContext *>(plNumber); 1069 if(pluralNumber.offset == 0) { 1070 // The number was already formatted with this formatter. 1071 appendTo.formatAndAppend(pluralNumber.formatter, pluralNumber.number, 1072 pluralNumber.numberString, success); 1073 } else { 1074 // Do not use the formatted (number-offset) string for a named argument 1075 // that formats the number without subtracting the offset. 1076 appendTo.formatAndAppend(pluralNumber.formatter, *arg, success); 1077 } 1078 } else if ((formatter = getCachedFormatter(i -2))) { 1079 // Handles all ArgType.SIMPLE, and formatters from setFormat() and its siblings. 1080 if (dynamic_cast<const ChoiceFormat*>(formatter) || 1081 dynamic_cast<const PluralFormat*>(formatter) || 1082 dynamic_cast<const SelectFormat*>(formatter)) { 1083 // We only handle nested formats here if they were provided via 1084 // setFormat() or its siblings. Otherwise they are not cached and instead 1085 // handled below according to argType. 1086 UnicodeString subMsgString; 1087 formatter->format(*arg, subMsgString, success); 1088 if (subMsgString.indexOf(LEFT_CURLY_BRACE) >= 0 || 1089 (subMsgString.indexOf(SINGLE_QUOTE) >= 0 && !MessageImpl::jdkAposMode(msgPattern)) 1090 ) { 1091 MessageFormat subMsgFormat(subMsgString, fLocale, success); 1092 subMsgFormat.format(0, NULL, arguments, argumentNames, cnt, appendTo, ignore, success); 1093 } else { 1094 appendTo.append(subMsgString); 1095 } 1096 } else { 1097 appendTo.formatAndAppend(formatter, *arg, success); 1098 } 1099 } else if (argType == UMSGPAT_ARG_TYPE_NONE || (cachedFormatters && uhash_iget(cachedFormatters, i - 2))) { 1100 // We arrive here if getCachedFormatter returned NULL, but there was actually an element in the hash table. 1101 // This can only happen if the hash table contained a DummyFormat, so the if statement above is a check 1102 // for the hash table containind DummyFormat. 1103 if (arg->isNumeric()) { 1104 const NumberFormat* nf = getDefaultNumberFormat(success); 1105 appendTo.formatAndAppend(nf, *arg, success); 1106 } else if (arg->getType() == Formattable::kDate) { 1107 const DateFormat* df = getDefaultDateFormat(success); 1108 appendTo.formatAndAppend(df, *arg, success); 1109 } else { 1110 appendTo.append(arg->getString(success)); 1111 } 1112 } else if (argType == UMSGPAT_ARG_TYPE_CHOICE) { 1113 if (!arg->isNumeric()) { 1114 success = U_ILLEGAL_ARGUMENT_ERROR; 1115 return; 1116 } 1117 // We must use the Formattable::getDouble() variant with the UErrorCode parameter 1118 // because only this one converts non-double numeric types to double. 1119 const double number = arg->getDouble(success); 1120 int32_t subMsgStart = ChoiceFormat::findSubMessage(msgPattern, i, number); 1121 formatComplexSubMessage(subMsgStart, NULL, arguments, argumentNames, 1122 cnt, appendTo, success); 1123 } else if (UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType)) { 1124 if (!arg->isNumeric()) { 1125 success = U_ILLEGAL_ARGUMENT_ERROR; 1126 return; 1127 } 1128 const PluralSelectorProvider &selector = 1129 argType == UMSGPAT_ARG_TYPE_PLURAL ? pluralProvider : ordinalProvider; 1130 // We must use the Formattable::getDouble() variant with the UErrorCode parameter 1131 // because only this one converts non-double numeric types to double. 1132 double offset = msgPattern.getPluralOffset(i); 1133 PluralSelectorContext context(i, argName, *arg, offset, success); 1134 int32_t subMsgStart = PluralFormat::findSubMessage( 1135 msgPattern, i, selector, &context, arg->getDouble(success), success); 1136 formatComplexSubMessage(subMsgStart, &context, arguments, argumentNames, 1137 cnt, appendTo, success); 1138 } else if (argType == UMSGPAT_ARG_TYPE_SELECT) { 1139 int32_t subMsgStart = SelectFormat::findSubMessage(msgPattern, i, arg->getString(success), success); 1140 formatComplexSubMessage(subMsgStart, NULL, arguments, argumentNames, 1141 cnt, appendTo, success); 1142 } else { 1143 // This should never happen. 1144 success = U_INTERNAL_PROGRAM_ERROR; 1145 return; 1146 } 1147 ignore = updateMetaData(appendTo, prevDestLength, ignore, arg); 1148 prevIndex = msgPattern.getPart(argLimit).getLimit(); 1149 i = argLimit; 1150 } 1151 } 1152 1153 1154 void MessageFormat::formatComplexSubMessage(int32_t msgStart, 1155 const void *plNumber, 1156 const Formattable* arguments, 1157 const UnicodeString *argumentNames, 1158 int32_t cnt, 1159 AppendableWrapper& appendTo, 1160 UErrorCode& success) const { 1161 if (U_FAILURE(success)) { 1162 return; 1163 } 1164 1165 if (!MessageImpl::jdkAposMode(msgPattern)) { 1166 format(msgStart, plNumber, arguments, argumentNames, cnt, appendTo, NULL, success); 1167 return; 1168 } 1169 1170 // JDK compatibility mode: (see JDK MessageFormat.format() API docs) 1171 // - remove SKIP_SYNTAX; that is, remove half of the apostrophes 1172 // - if the result string contains an open curly brace '{' then 1173 // instantiate a temporary MessageFormat object and format again; 1174 // otherwise just append the result string 1175 const UnicodeString& msgString = msgPattern.getPatternString(); 1176 UnicodeString sb; 1177 int32_t prevIndex = msgPattern.getPart(msgStart).getLimit(); 1178 for (int32_t i = msgStart;;) { 1179 const MessagePattern::Part& part = msgPattern.getPart(++i); 1180 const UMessagePatternPartType type = part.getType(); 1181 int32_t index = part.getIndex(); 1182 if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) { 1183 sb.append(msgString, prevIndex, index - prevIndex); 1184 break; 1185 } else if (type == UMSGPAT_PART_TYPE_REPLACE_NUMBER || type == UMSGPAT_PART_TYPE_SKIP_SYNTAX) { 1186 sb.append(msgString, prevIndex, index - prevIndex); 1187 if (type == UMSGPAT_PART_TYPE_REPLACE_NUMBER) { 1188 const PluralSelectorContext &pluralNumber = 1189 *static_cast<const PluralSelectorContext *>(plNumber); 1190 if(pluralNumber.forReplaceNumber) { 1191 // number-offset was already formatted. 1192 sb.append(pluralNumber.numberString); 1193 } else { 1194 const NumberFormat* nf = getDefaultNumberFormat(success); 1195 sb.append(nf->format(pluralNumber.number, sb, success)); 1196 } 1197 } 1198 prevIndex = part.getLimit(); 1199 } else if (type == UMSGPAT_PART_TYPE_ARG_START) { 1200 sb.append(msgString, prevIndex, index - prevIndex); 1201 prevIndex = index; 1202 i = msgPattern.getLimitPartIndex(i); 1203 index = msgPattern.getPart(i).getLimit(); 1204 MessageImpl::appendReducedApostrophes(msgString, prevIndex, index, sb); 1205 prevIndex = index; 1206 } 1207 } 1208 if (sb.indexOf(LEFT_CURLY_BRACE) >= 0) { 1209 UnicodeString emptyPattern; // gcc 3.3.3 fails with "UnicodeString()" as the first parameter. 1210 MessageFormat subMsgFormat(emptyPattern, fLocale, success); 1211 subMsgFormat.applyPattern(sb, UMSGPAT_APOS_DOUBLE_REQUIRED, NULL, success); 1212 subMsgFormat.format(0, NULL, arguments, argumentNames, cnt, appendTo, NULL, success); 1213 } else { 1214 appendTo.append(sb); 1215 } 1216 } 1217 1218 1219 UnicodeString MessageFormat::getLiteralStringUntilNextArgument(int32_t from) const { 1220 const UnicodeString& msgString=msgPattern.getPatternString(); 1221 int32_t prevIndex=msgPattern.getPart(from).getLimit(); 1222 UnicodeString b; 1223 for (int32_t i = from + 1; ; ++i) { 1224 const MessagePattern::Part& part = msgPattern.getPart(i); 1225 const UMessagePatternPartType type=part.getType(); 1226 int32_t index=part.getIndex(); 1227 b.append(msgString, prevIndex, index - prevIndex); 1228 if(type==UMSGPAT_PART_TYPE_ARG_START || type==UMSGPAT_PART_TYPE_MSG_LIMIT) { 1229 return b; 1230 } 1231 // Unexpected Part "part" in parsed message. 1232 U_ASSERT(type==UMSGPAT_PART_TYPE_SKIP_SYNTAX || type==UMSGPAT_PART_TYPE_INSERT_CHAR); 1233 prevIndex=part.getLimit(); 1234 } 1235 } 1236 1237 1238 FieldPosition* MessageFormat::updateMetaData(AppendableWrapper& /*dest*/, int32_t /*prevLength*/, 1239 FieldPosition* /*fp*/, const Formattable* /*argId*/) const { 1240 // Unlike in Java, there are no field attributes defined for MessageFormat. Do nothing. 1241 return NULL; 1242 /* 1243 if (fp != NULL && Field.ARGUMENT.equals(fp.getFieldAttribute())) { 1244 fp->setBeginIndex(prevLength); 1245 fp->setEndIndex(dest.get_length()); 1246 return NULL; 1247 } 1248 return fp; 1249 */ 1250 } 1251 1252 int32_t 1253 MessageFormat::findOtherSubMessage(int32_t partIndex) const { 1254 int32_t count=msgPattern.countParts(); 1255 const MessagePattern::Part *part = &msgPattern.getPart(partIndex); 1256 if(MessagePattern::Part::hasNumericValue(part->getType())) { 1257 ++partIndex; 1258 } 1259 // Iterate over (ARG_SELECTOR [ARG_INT|ARG_DOUBLE] message) tuples 1260 // until ARG_LIMIT or end of plural-only pattern. 1261 UnicodeString other(FALSE, OTHER_STRING, 5); 1262 do { 1263 part=&msgPattern.getPart(partIndex++); 1264 UMessagePatternPartType type=part->getType(); 1265 if(type==UMSGPAT_PART_TYPE_ARG_LIMIT) { 1266 break; 1267 } 1268 U_ASSERT(type==UMSGPAT_PART_TYPE_ARG_SELECTOR); 1269 // part is an ARG_SELECTOR followed by an optional explicit value, and then a message 1270 if(msgPattern.partSubstringMatches(*part, other)) { 1271 return partIndex; 1272 } 1273 if(MessagePattern::Part::hasNumericValue(msgPattern.getPartType(partIndex))) { 1274 ++partIndex; // skip the numeric-value part of "=1" etc. 1275 } 1276 partIndex=msgPattern.getLimitPartIndex(partIndex); 1277 } while(++partIndex<count); 1278 return 0; 1279 } 1280 1281 int32_t 1282 MessageFormat::findFirstPluralNumberArg(int32_t msgStart, const UnicodeString &argName) const { 1283 for(int32_t i=msgStart+1;; ++i) { 1284 const MessagePattern::Part &part=msgPattern.getPart(i); 1285 UMessagePatternPartType type=part.getType(); 1286 if(type==UMSGPAT_PART_TYPE_MSG_LIMIT) { 1287 return 0; 1288 } 1289 if(type==UMSGPAT_PART_TYPE_REPLACE_NUMBER) { 1290 return -1; 1291 } 1292 if(type==UMSGPAT_PART_TYPE_ARG_START) { 1293 UMessagePatternArgType argType=part.getArgType(); 1294 if(!argName.isEmpty() && (argType==UMSGPAT_ARG_TYPE_NONE || argType==UMSGPAT_ARG_TYPE_SIMPLE)) { 1295 // ARG_NUMBER or ARG_NAME 1296 if(msgPattern.partSubstringMatches(msgPattern.getPart(i+1), argName)) { 1297 return i; 1298 } 1299 } 1300 i=msgPattern.getLimitPartIndex(i); 1301 } 1302 } 1303 } 1304 1305 void MessageFormat::copyObjects(const MessageFormat& that, UErrorCode& ec) { 1306 // Deep copy pointer fields. 1307 // We need not copy the formatAliases because they are re-filled 1308 // in each getFormats() call. 1309 // The defaultNumberFormat, defaultDateFormat and pluralProvider.rules 1310 // also get created on demand. 1311 argTypeCount = that.argTypeCount; 1312 if (argTypeCount > 0) { 1313 if (!allocateArgTypes(argTypeCount, ec)) { 1314 return; 1315 } 1316 uprv_memcpy(argTypes, that.argTypes, argTypeCount * sizeof(argTypes[0])); 1317 } 1318 if (cachedFormatters != NULL) { 1319 uhash_removeAll(cachedFormatters); 1320 } 1321 if (customFormatArgStarts != NULL) { 1322 uhash_removeAll(customFormatArgStarts); 1323 } 1324 if (that.cachedFormatters) { 1325 if (cachedFormatters == NULL) { 1326 cachedFormatters=uhash_open(uhash_hashLong, uhash_compareLong, 1327 equalFormatsForHash, &ec); 1328 if (U_FAILURE(ec)) { 1329 return; 1330 } 1331 uhash_setValueDeleter(cachedFormatters, uprv_deleteUObject); 1332 } 1333 1334 const int32_t count = uhash_count(that.cachedFormatters); 1335 int32_t pos, idx; 1336 for (idx = 0, pos = UHASH_FIRST; idx < count && U_SUCCESS(ec); ++idx) { 1337 const UHashElement* cur = uhash_nextElement(that.cachedFormatters, &pos); 1338 Format* newFormat = ((Format*)(cur->value.pointer))->clone(); 1339 if (newFormat) { 1340 uhash_iput(cachedFormatters, cur->key.integer, newFormat, &ec); 1341 } else { 1342 ec = U_MEMORY_ALLOCATION_ERROR; 1343 return; 1344 } 1345 } 1346 } 1347 if (that.customFormatArgStarts) { 1348 if (customFormatArgStarts == NULL) { 1349 customFormatArgStarts=uhash_open(uhash_hashLong, uhash_compareLong, 1350 NULL, &ec); 1351 } 1352 const int32_t count = uhash_count(that.customFormatArgStarts); 1353 int32_t pos, idx; 1354 for (idx = 0, pos = UHASH_FIRST; idx < count && U_SUCCESS(ec); ++idx) { 1355 const UHashElement* cur = uhash_nextElement(that.customFormatArgStarts, &pos); 1356 uhash_iputi(customFormatArgStarts, cur->key.integer, cur->value.integer, &ec); 1357 } 1358 } 1359 } 1360 1361 1362 Formattable* 1363 MessageFormat::parse(int32_t msgStart, 1364 const UnicodeString& source, 1365 ParsePosition& pos, 1366 int32_t& count, 1367 UErrorCode& ec) const { 1368 count = 0; 1369 if (U_FAILURE(ec)) { 1370 pos.setErrorIndex(pos.getIndex()); 1371 return NULL; 1372 } 1373 // parse() does not work with named arguments. 1374 if (msgPattern.hasNamedArguments()) { 1375 ec = U_ARGUMENT_TYPE_MISMATCH; 1376 pos.setErrorIndex(pos.getIndex()); 1377 return NULL; 1378 } 1379 LocalArray<Formattable> resultArray(new Formattable[argTypeCount ? argTypeCount : 1]); 1380 const UnicodeString& msgString=msgPattern.getPatternString(); 1381 int32_t prevIndex=msgPattern.getPart(msgStart).getLimit(); 1382 int32_t sourceOffset = pos.getIndex(); 1383 ParsePosition tempStatus(0); 1384 1385 for(int32_t i=msgStart+1; ; ++i) { 1386 UBool haveArgResult = FALSE; 1387 const MessagePattern::Part* part=&msgPattern.getPart(i); 1388 const UMessagePatternPartType type=part->getType(); 1389 int32_t index=part->getIndex(); 1390 // Make sure the literal string matches. 1391 int32_t len = index - prevIndex; 1392 if (len == 0 || (0 == msgString.compare(prevIndex, len, source, sourceOffset, len))) { 1393 sourceOffset += len; 1394 prevIndex += len; 1395 } else { 1396 pos.setErrorIndex(sourceOffset); 1397 return NULL; // leave index as is to signal error 1398 } 1399 if(type==UMSGPAT_PART_TYPE_MSG_LIMIT) { 1400 // Things went well! Done. 1401 pos.setIndex(sourceOffset); 1402 return resultArray.orphan(); 1403 } 1404 if(type==UMSGPAT_PART_TYPE_SKIP_SYNTAX || type==UMSGPAT_PART_TYPE_INSERT_CHAR) { 1405 prevIndex=part->getLimit(); 1406 continue; 1407 } 1408 // We do not support parsing Plural formats. (No REPLACE_NUMBER here.) 1409 // Unexpected Part "part" in parsed message. 1410 U_ASSERT(type==UMSGPAT_PART_TYPE_ARG_START); 1411 int32_t argLimit=msgPattern.getLimitPartIndex(i); 1412 1413 UMessagePatternArgType argType=part->getArgType(); 1414 part=&msgPattern.getPart(++i); 1415 int32_t argNumber = part->getValue(); // ARG_NUMBER 1416 UnicodeString key; 1417 ++i; 1418 const Format* formatter = NULL; 1419 Formattable& argResult = resultArray[argNumber]; 1420 1421 if(cachedFormatters!=NULL && (formatter = getCachedFormatter(i - 2))!=NULL) { 1422 // Just parse using the formatter. 1423 tempStatus.setIndex(sourceOffset); 1424 formatter->parseObject(source, argResult, tempStatus); 1425 if (tempStatus.getIndex() == sourceOffset) { 1426 pos.setErrorIndex(sourceOffset); 1427 return NULL; // leave index as is to signal error 1428 } 1429 sourceOffset = tempStatus.getIndex(); 1430 haveArgResult = TRUE; 1431 } else if( 1432 argType==UMSGPAT_ARG_TYPE_NONE || (cachedFormatters && uhash_iget(cachedFormatters, i -2))) { 1433 // We arrive here if getCachedFormatter returned NULL, but there was actually an element in the hash table. 1434 // This can only happen if the hash table contained a DummyFormat, so the if statement above is a check 1435 // for the hash table containind DummyFormat. 1436 1437 // Match as a string. 1438 // if at end, use longest possible match 1439 // otherwise uses first match to intervening string 1440 // does NOT recursively try all possibilities 1441 UnicodeString stringAfterArgument = getLiteralStringUntilNextArgument(argLimit); 1442 int32_t next; 1443 if (!stringAfterArgument.isEmpty()) { 1444 next = source.indexOf(stringAfterArgument, sourceOffset); 1445 } else { 1446 next = source.length(); 1447 } 1448 if (next < 0) { 1449 pos.setErrorIndex(sourceOffset); 1450 return NULL; // leave index as is to signal error 1451 } else { 1452 UnicodeString strValue(source.tempSubString(sourceOffset, next - sourceOffset)); 1453 UnicodeString compValue; 1454 compValue.append(LEFT_CURLY_BRACE); 1455 itos(argNumber, compValue); 1456 compValue.append(RIGHT_CURLY_BRACE); 1457 if (0 != strValue.compare(compValue)) { 1458 argResult.setString(strValue); 1459 haveArgResult = TRUE; 1460 } 1461 sourceOffset = next; 1462 } 1463 } else if(argType==UMSGPAT_ARG_TYPE_CHOICE) { 1464 tempStatus.setIndex(sourceOffset); 1465 double choiceResult = ChoiceFormat::parseArgument(msgPattern, i, source, tempStatus); 1466 if (tempStatus.getIndex() == sourceOffset) { 1467 pos.setErrorIndex(sourceOffset); 1468 return NULL; // leave index as is to signal error 1469 } 1470 argResult.setDouble(choiceResult); 1471 haveArgResult = TRUE; 1472 sourceOffset = tempStatus.getIndex(); 1473 } else if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) || argType==UMSGPAT_ARG_TYPE_SELECT) { 1474 // Parsing not supported. 1475 ec = U_UNSUPPORTED_ERROR; 1476 return NULL; 1477 } else { 1478 // This should never happen. 1479 ec = U_INTERNAL_PROGRAM_ERROR; 1480 return NULL; 1481 } 1482 if (haveArgResult && count <= argNumber) { 1483 count = argNumber + 1; 1484 } 1485 prevIndex=msgPattern.getPart(argLimit).getLimit(); 1486 i=argLimit; 1487 } 1488 } 1489 // ------------------------------------- 1490 // Parses the source pattern and returns the Formattable objects array, 1491 // the array count and the ending parse position. The caller of this method 1492 // owns the array. 1493 1494 Formattable* 1495 MessageFormat::parse(const UnicodeString& source, 1496 ParsePosition& pos, 1497 int32_t& count) const { 1498 UErrorCode ec = U_ZERO_ERROR; 1499 return parse(0, source, pos, count, ec); 1500 } 1501 1502 // ------------------------------------- 1503 // Parses the source string and returns the array of 1504 // Formattable objects and the array count. The caller 1505 // owns the returned array. 1506 1507 Formattable* 1508 MessageFormat::parse(const UnicodeString& source, 1509 int32_t& cnt, 1510 UErrorCode& success) const 1511 { 1512 if (msgPattern.hasNamedArguments()) { 1513 success = U_ARGUMENT_TYPE_MISMATCH; 1514 return NULL; 1515 } 1516 ParsePosition status(0); 1517 // Calls the actual implementation method and starts 1518 // from zero offset of the source text. 1519 Formattable* result = parse(source, status, cnt); 1520 if (status.getIndex() == 0) { 1521 success = U_MESSAGE_PARSE_ERROR; 1522 delete[] result; 1523 return NULL; 1524 } 1525 return result; 1526 } 1527 1528 // ------------------------------------- 1529 // Parses the source text and copy into the result buffer. 1530 1531 void 1532 MessageFormat::parseObject( const UnicodeString& source, 1533 Formattable& result, 1534 ParsePosition& status) const 1535 { 1536 int32_t cnt = 0; 1537 Formattable* tmpResult = parse(source, status, cnt); 1538 if (tmpResult != NULL) 1539 result.adoptArray(tmpResult, cnt); 1540 } 1541 1542 UnicodeString 1543 MessageFormat::autoQuoteApostrophe(const UnicodeString& pattern, UErrorCode& status) { 1544 UnicodeString result; 1545 if (U_SUCCESS(status)) { 1546 int32_t plen = pattern.length(); 1547 const UChar* pat = pattern.getBuffer(); 1548 int32_t blen = plen * 2 + 1; // space for null termination, convenience 1549 UChar* buf = result.getBuffer(blen); 1550 if (buf == NULL) { 1551 status = U_MEMORY_ALLOCATION_ERROR; 1552 } else { 1553 int32_t len = umsg_autoQuoteApostrophe(pat, plen, buf, blen, &status); 1554 result.releaseBuffer(U_SUCCESS(status) ? len : 0); 1555 } 1556 } 1557 if (U_FAILURE(status)) { 1558 result.setToBogus(); 1559 } 1560 return result; 1561 } 1562 1563 // ------------------------------------- 1564 1565 static Format* makeRBNF(URBNFRuleSetTag tag, const Locale& locale, const UnicodeString& defaultRuleSet, UErrorCode& ec) { 1566 RuleBasedNumberFormat* fmt = new RuleBasedNumberFormat(tag, locale, ec); 1567 if (fmt == NULL) { 1568 ec = U_MEMORY_ALLOCATION_ERROR; 1569 } else if (U_SUCCESS(ec) && defaultRuleSet.length() > 0) { 1570 UErrorCode localStatus = U_ZERO_ERROR; // ignore unrecognized default rule set 1571 fmt->setDefaultRuleSet(defaultRuleSet, localStatus); 1572 } 1573 return fmt; 1574 } 1575 1576 void MessageFormat::cacheExplicitFormats(UErrorCode& status) { 1577 if (U_FAILURE(status)) { 1578 return; 1579 } 1580 1581 if (cachedFormatters != NULL) { 1582 uhash_removeAll(cachedFormatters); 1583 } 1584 if (customFormatArgStarts != NULL) { 1585 uhash_removeAll(customFormatArgStarts); 1586 } 1587 1588 // The last two "parts" can at most be ARG_LIMIT and MSG_LIMIT 1589 // which we need not examine. 1590 int32_t limit = msgPattern.countParts() - 2; 1591 argTypeCount = 0; 1592 // We also need not look at the first two "parts" 1593 // (at most MSG_START and ARG_START) in this loop. 1594 // We determine the argTypeCount first so that we can allocateArgTypes 1595 // so that the next loop can set argTypes[argNumber]. 1596 // (This is for the C API which needs the argTypes to read its va_arg list.) 1597 for (int32_t i = 2; i < limit && U_SUCCESS(status); ++i) { 1598 const MessagePattern::Part& part = msgPattern.getPart(i); 1599 if (part.getType() == UMSGPAT_PART_TYPE_ARG_NUMBER) { 1600 const int argNumber = part.getValue(); 1601 if (argNumber >= argTypeCount) { 1602 argTypeCount = argNumber + 1; 1603 } 1604 } 1605 } 1606 if (!allocateArgTypes(argTypeCount, status)) { 1607 return; 1608 } 1609 // Set all argTypes to kObject, as a "none" value, for lack of any better value. 1610 // We never use kObject for real arguments. 1611 // We use it as "no argument yet" for the check for hasArgTypeConflicts. 1612 for (int32_t i = 0; i < argTypeCount; ++i) { 1613 argTypes[i] = Formattable::kObject; 1614 } 1615 hasArgTypeConflicts = FALSE; 1616 1617 // This loop starts at part index 1 because we do need to examine 1618 // ARG_START parts. (But we can ignore the MSG_START.) 1619 for (int32_t i = 1; i < limit && U_SUCCESS(status); ++i) { 1620 const MessagePattern::Part* part = &msgPattern.getPart(i); 1621 if (part->getType() != UMSGPAT_PART_TYPE_ARG_START) { 1622 continue; 1623 } 1624 UMessagePatternArgType argType = part->getArgType(); 1625 1626 int32_t argNumber = -1; 1627 part = &msgPattern.getPart(i + 1); 1628 if (part->getType() == UMSGPAT_PART_TYPE_ARG_NUMBER) { 1629 argNumber = part->getValue(); 1630 } 1631 Formattable::Type formattableType; 1632 1633 switch (argType) { 1634 case UMSGPAT_ARG_TYPE_NONE: 1635 formattableType = Formattable::kString; 1636 break; 1637 case UMSGPAT_ARG_TYPE_SIMPLE: { 1638 int32_t index = i; 1639 i += 2; 1640 UnicodeString explicitType = msgPattern.getSubstring(msgPattern.getPart(i++)); 1641 UnicodeString style; 1642 if ((part = &msgPattern.getPart(i))->getType() == UMSGPAT_PART_TYPE_ARG_STYLE) { 1643 style = msgPattern.getSubstring(*part); 1644 ++i; 1645 } 1646 UParseError parseError; 1647 Format* formatter = createAppropriateFormat(explicitType, style, formattableType, parseError, status); 1648 setArgStartFormat(index, formatter, status); 1649 break; 1650 } 1651 case UMSGPAT_ARG_TYPE_CHOICE: 1652 case UMSGPAT_ARG_TYPE_PLURAL: 1653 case UMSGPAT_ARG_TYPE_SELECTORDINAL: 1654 formattableType = Formattable::kDouble; 1655 break; 1656 case UMSGPAT_ARG_TYPE_SELECT: 1657 formattableType = Formattable::kString; 1658 break; 1659 default: 1660 status = U_INTERNAL_PROGRAM_ERROR; // Should be unreachable. 1661 formattableType = Formattable::kString; 1662 break; 1663 } 1664 if (argNumber != -1) { 1665 if (argTypes[argNumber] != Formattable::kObject && argTypes[argNumber] != formattableType) { 1666 hasArgTypeConflicts = TRUE; 1667 } 1668 argTypes[argNumber] = formattableType; 1669 } 1670 } 1671 } 1672 1673 1674 Format* MessageFormat::createAppropriateFormat(UnicodeString& type, UnicodeString& style, 1675 Formattable::Type& formattableType, UParseError& parseError, 1676 UErrorCode& ec) { 1677 if (U_FAILURE(ec)) { 1678 return NULL; 1679 } 1680 Format* fmt = NULL; 1681 int32_t typeID, styleID; 1682 DateFormat::EStyle date_style; 1683 1684 switch (typeID = findKeyword(type, TYPE_IDS)) { 1685 case 0: // number 1686 formattableType = Formattable::kDouble; 1687 switch (findKeyword(style, NUMBER_STYLE_IDS)) { 1688 case 0: // default 1689 fmt = NumberFormat::createInstance(fLocale, ec); 1690 break; 1691 case 1: // currency 1692 fmt = NumberFormat::createCurrencyInstance(fLocale, ec); 1693 break; 1694 case 2: // percent 1695 fmt = NumberFormat::createPercentInstance(fLocale, ec); 1696 break; 1697 case 3: // integer 1698 formattableType = Formattable::kLong; 1699 fmt = createIntegerFormat(fLocale, ec); 1700 break; 1701 default: // pattern 1702 fmt = NumberFormat::createInstance(fLocale, ec); 1703 if (fmt) { 1704 DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fmt); 1705 if (decfmt != NULL) { 1706 decfmt->applyPattern(style,parseError,ec); 1707 } 1708 } 1709 break; 1710 } 1711 break; 1712 1713 case 1: // date 1714 case 2: // time 1715 formattableType = Formattable::kDate; 1716 styleID = findKeyword(style, DATE_STYLE_IDS); 1717 date_style = (styleID >= 0) ? DATE_STYLES[styleID] : DateFormat::kDefault; 1718 1719 if (typeID == 1) { 1720 fmt = DateFormat::createDateInstance(date_style, fLocale); 1721 } else { 1722 fmt = DateFormat::createTimeInstance(date_style, fLocale); 1723 } 1724 1725 if (styleID < 0 && fmt != NULL) { 1726 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(fmt); 1727 if (sdtfmt != NULL) { 1728 sdtfmt->applyPattern(style); 1729 } 1730 } 1731 break; 1732 1733 case 3: // spellout 1734 formattableType = Formattable::kDouble; 1735 fmt = makeRBNF(URBNF_SPELLOUT, fLocale, style, ec); 1736 break; 1737 case 4: // ordinal 1738 formattableType = Formattable::kDouble; 1739 fmt = makeRBNF(URBNF_ORDINAL, fLocale, style, ec); 1740 break; 1741 case 5: // duration 1742 formattableType = Formattable::kDouble; 1743 fmt = makeRBNF(URBNF_DURATION, fLocale, style, ec); 1744 break; 1745 default: 1746 formattableType = Formattable::kString; 1747 ec = U_ILLEGAL_ARGUMENT_ERROR; 1748 break; 1749 } 1750 1751 return fmt; 1752 } 1753 1754 1755 //------------------------------------- 1756 // Finds the string, s, in the string array, list. 1757 int32_t MessageFormat::findKeyword(const UnicodeString& s, 1758 const UChar * const *list) 1759 { 1760 if (s.isEmpty()) { 1761 return 0; // default 1762 } 1763 1764 int32_t length = s.length(); 1765 const UChar *ps = PatternProps::trimWhiteSpace(s.getBuffer(), length); 1766 UnicodeString buffer(FALSE, ps, length); 1767 // Trims the space characters and turns all characters 1768 // in s to lower case. 1769 buffer.toLower(""); 1770 for (int32_t i = 0; list[i]; ++i) { 1771 if (!buffer.compare(list[i], u_strlen(list[i]))) { 1772 return i; 1773 } 1774 } 1775 return -1; 1776 } 1777 1778 /** 1779 * Convenience method that ought to be in NumberFormat 1780 */ 1781 NumberFormat* 1782 MessageFormat::createIntegerFormat(const Locale& locale, UErrorCode& status) const { 1783 NumberFormat *temp = NumberFormat::createInstance(locale, status); 1784 DecimalFormat *temp2; 1785 if (temp != NULL && (temp2 = dynamic_cast<DecimalFormat*>(temp)) != NULL) { 1786 temp2->setMaximumFractionDigits(0); 1787 temp2->setDecimalSeparatorAlwaysShown(FALSE); 1788 temp2->setParseIntegerOnly(TRUE); 1789 } 1790 1791 return temp; 1792 } 1793 1794 /** 1795 * Return the default number format. Used to format a numeric 1796 * argument when subformats[i].format is NULL. Returns NULL 1797 * on failure. 1798 * 1799 * Semantically const but may modify *this. 1800 */ 1801 const NumberFormat* MessageFormat::getDefaultNumberFormat(UErrorCode& ec) const { 1802 if (defaultNumberFormat == NULL) { 1803 MessageFormat* t = (MessageFormat*) this; 1804 t->defaultNumberFormat = NumberFormat::createInstance(fLocale, ec); 1805 if (U_FAILURE(ec)) { 1806 delete t->defaultNumberFormat; 1807 t->defaultNumberFormat = NULL; 1808 } else if (t->defaultNumberFormat == NULL) { 1809 ec = U_MEMORY_ALLOCATION_ERROR; 1810 } 1811 } 1812 return defaultNumberFormat; 1813 } 1814 1815 /** 1816 * Return the default date format. Used to format a date 1817 * argument when subformats[i].format is NULL. Returns NULL 1818 * on failure. 1819 * 1820 * Semantically const but may modify *this. 1821 */ 1822 const DateFormat* MessageFormat::getDefaultDateFormat(UErrorCode& ec) const { 1823 if (defaultDateFormat == NULL) { 1824 MessageFormat* t = (MessageFormat*) this; 1825 t->defaultDateFormat = DateFormat::createDateTimeInstance(DateFormat::kShort, DateFormat::kShort, fLocale); 1826 if (t->defaultDateFormat == NULL) { 1827 ec = U_MEMORY_ALLOCATION_ERROR; 1828 } 1829 } 1830 return defaultDateFormat; 1831 } 1832 1833 UBool 1834 MessageFormat::usesNamedArguments() const { 1835 return msgPattern.hasNamedArguments(); 1836 } 1837 1838 int32_t 1839 MessageFormat::getArgTypeCount() const { 1840 return argTypeCount; 1841 } 1842 1843 UBool MessageFormat::equalFormats(const void* left, const void* right) { 1844 return *(const Format*)left==*(const Format*)right; 1845 } 1846 1847 1848 UBool MessageFormat::DummyFormat::operator==(const Format&) const { 1849 return TRUE; 1850 } 1851 1852 Format* MessageFormat::DummyFormat::clone() const { 1853 return new DummyFormat(); 1854 } 1855 1856 UnicodeString& MessageFormat::DummyFormat::format(const Formattable&, 1857 UnicodeString& appendTo, 1858 UErrorCode& status) const { 1859 if (U_SUCCESS(status)) { 1860 status = U_UNSUPPORTED_ERROR; 1861 } 1862 return appendTo; 1863 } 1864 1865 UnicodeString& MessageFormat::DummyFormat::format(const Formattable&, 1866 UnicodeString& appendTo, 1867 FieldPosition&, 1868 UErrorCode& status) const { 1869 if (U_SUCCESS(status)) { 1870 status = U_UNSUPPORTED_ERROR; 1871 } 1872 return appendTo; 1873 } 1874 1875 UnicodeString& MessageFormat::DummyFormat::format(const Formattable&, 1876 UnicodeString& appendTo, 1877 FieldPositionIterator*, 1878 UErrorCode& status) const { 1879 if (U_SUCCESS(status)) { 1880 status = U_UNSUPPORTED_ERROR; 1881 } 1882 return appendTo; 1883 } 1884 1885 void MessageFormat::DummyFormat::parseObject(const UnicodeString&, 1886 Formattable&, 1887 ParsePosition& ) const { 1888 } 1889 1890 1891 FormatNameEnumeration::FormatNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) { 1892 pos=0; 1893 fFormatNames = fNameList; 1894 } 1895 1896 const UnicodeString* 1897 FormatNameEnumeration::snext(UErrorCode& status) { 1898 if (U_SUCCESS(status) && pos < fFormatNames->size()) { 1899 return (const UnicodeString*)fFormatNames->elementAt(pos++); 1900 } 1901 return NULL; 1902 } 1903 1904 void 1905 FormatNameEnumeration::reset(UErrorCode& /*status*/) { 1906 pos=0; 1907 } 1908 1909 int32_t 1910 FormatNameEnumeration::count(UErrorCode& /*status*/) const { 1911 return (fFormatNames==NULL) ? 0 : fFormatNames->size(); 1912 } 1913 1914 FormatNameEnumeration::~FormatNameEnumeration() { 1915 delete fFormatNames; 1916 } 1917 1918 MessageFormat::PluralSelectorProvider::PluralSelectorProvider(const MessageFormat &mf, UPluralType t) 1919 : msgFormat(mf), rules(NULL), type(t) { 1920 } 1921 1922 MessageFormat::PluralSelectorProvider::~PluralSelectorProvider() { 1923 delete rules; 1924 } 1925 1926 UnicodeString MessageFormat::PluralSelectorProvider::select(void *ctx, double number, 1927 UErrorCode& ec) const { 1928 if (U_FAILURE(ec)) { 1929 return UnicodeString(FALSE, OTHER_STRING, 5); 1930 } 1931 MessageFormat::PluralSelectorProvider* t = const_cast<MessageFormat::PluralSelectorProvider*>(this); 1932 if(rules == NULL) { 1933 t->rules = PluralRules::forLocale(msgFormat.fLocale, type, ec); 1934 if (U_FAILURE(ec)) { 1935 return UnicodeString(FALSE, OTHER_STRING, 5); 1936 } 1937 } 1938 // Select a sub-message according to how the number is formatted, 1939 // which is specified in the selected sub-message. 1940 // We avoid this circle by looking at how 1941 // the number is formatted in the "other" sub-message 1942 // which must always be present and usually contains the number. 1943 // Message authors should be consistent across sub-messages. 1944 PluralSelectorContext &context = *static_cast<PluralSelectorContext *>(ctx); 1945 int32_t otherIndex = msgFormat.findOtherSubMessage(context.startIndex); 1946 context.numberArgIndex = msgFormat.findFirstPluralNumberArg(otherIndex, context.argName); 1947 if(context.numberArgIndex > 0 && msgFormat.cachedFormatters != NULL) { 1948 context.formatter = 1949 (const Format*)uhash_iget(msgFormat.cachedFormatters, context.numberArgIndex); 1950 } 1951 if(context.formatter == NULL) { 1952 context.formatter = msgFormat.getDefaultNumberFormat(ec); 1953 context.forReplaceNumber = TRUE; 1954 } 1955 U_ASSERT(context.number.getDouble(ec) == number); // argument number minus the offset 1956 context.formatter->format(context.number, context.numberString, ec); 1957 const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(context.formatter); 1958 if(decFmt != NULL) { 1959 VisibleDigitsWithExponent digits; 1960 decFmt->initVisibleDigitsWithExponent(context.number, digits, ec); 1961 if (U_FAILURE(ec)) { 1962 return UnicodeString(FALSE, OTHER_STRING, 5); 1963 } 1964 return rules->select(digits); 1965 } else { 1966 return rules->select(number); 1967 } 1968 } 1969 1970 void MessageFormat::PluralSelectorProvider::reset() { 1971 delete rules; 1972 rules = NULL; 1973 } 1974 1975 1976 U_NAMESPACE_END 1977 1978 #endif /* #if !UCONFIG_NO_FORMATTING */ 1979 1980 //eof 1981