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