1 // 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /******************************************************************** 4 * COPYRIGHT: 5 * Copyright (c) 1997-2015, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ******************************************************************** 8 * 9 * File MSGFMT.CPP 10 * 11 * Modification History: 12 * 13 * Date Name Description 14 * 02/19/97 aliu Converted from java. 15 * 03/20/97 helena Finished first cut of implementation. 16 * 04/10/97 aliu Made to work on AIX. Added stoi to replace wtoi. 17 * 06/11/97 helena Fixed addPattern to take the pattern correctly. 18 * 06/17/97 helena Fixed the getPattern to return the correct pattern. 19 * 07/09/97 helena Made ParsePosition into a class. 20 * 02/22/99 stephen Removed character literals for EBCDIC safety 21 * 11/01/09 kirtig Added SelectFormat 22 ********************************************************************/ 23 24 #include "unicode/utypes.h" 25 26 #if !UCONFIG_NO_FORMATTING 27 28 #include "unicode/appendable.h" 29 #include "unicode/choicfmt.h" 30 #include "unicode/datefmt.h" 31 #include "unicode/decimfmt.h" 32 #include "unicode/localpointer.h" 33 #include "unicode/msgfmt.h" 34 #include "unicode/numberformatter.h" 35 #include "unicode/plurfmt.h" 36 #include "unicode/rbnf.h" 37 #include "unicode/selfmt.h" 38 #include "unicode/smpdtfmt.h" 39 #include "unicode/umsg.h" 40 #include "unicode/ustring.h" 41 #include "cmemory.h" 42 #include "patternprops.h" 43 #include "messageimpl.h" 44 #include "msgfmt_impl.h" 45 #include "plurrule_impl.h" 46 #include "uassert.h" 47 #include "uelement.h" 48 #include "uhash.h" 49 #include "ustrfmt.h" 50 #include "util.h" 51 #include "uvector.h" 52 #include "number_decimalquantity.h" 53 54 // ***************************************************************************** 55 // class MessageFormat 56 // ***************************************************************************** 57 58 #define SINGLE_QUOTE ((UChar)0x0027) 59 #define COMMA ((UChar)0x002C) 60 #define LEFT_CURLY_BRACE ((UChar)0x007B) 61 #define RIGHT_CURLY_BRACE ((UChar)0x007D) 62 63 //--------------------------------------- 64 // static data 65 66 static const UChar ID_NUMBER[] = { 67 0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0 /* "number" */ 68 }; 69 static const UChar ID_DATE[] = { 70 0x64, 0x61, 0x74, 0x65, 0 /* "date" */ 71 }; 72 static const UChar ID_TIME[] = { 73 0x74, 0x69, 0x6D, 0x65, 0 /* "time" */ 74 }; 75 static const UChar ID_SPELLOUT[] = { 76 0x73, 0x70, 0x65, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0 /* "spellout" */ 77 }; 78 static const UChar ID_ORDINAL[] = { 79 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0 /* "ordinal" */ 80 }; 81 static const UChar ID_DURATION[] = { 82 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0 /* "duration" */ 83 }; 84 85 // MessageFormat Type List Number, Date, Time or Choice 86 static const UChar * const TYPE_IDS[] = { 87 ID_NUMBER, 88 ID_DATE, 89 ID_TIME, 90 ID_SPELLOUT, 91 ID_ORDINAL, 92 ID_DURATION, 93 NULL, 94 }; 95 96 static const UChar ID_EMPTY[] = { 97 0 /* empty string, used for default so that null can mark end of list */ 98 }; 99 static const UChar ID_CURRENCY[] = { 100 0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x63, 0x79, 0 /* "currency" */ 101 }; 102 static const UChar ID_PERCENT[] = { 103 0x70, 0x65, 0x72, 0x63, 0x65, 0x6E, 0x74, 0 /* "percent" */ 104 }; 105 static const UChar ID_INTEGER[] = { 106 0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0 /* "integer" */ 107 }; 108 109 // NumberFormat modifier list, default, currency, percent or integer 110 static const UChar * const NUMBER_STYLE_IDS[] = { 111 ID_EMPTY, 112 ID_CURRENCY, 113 ID_PERCENT, 114 ID_INTEGER, 115 NULL, 116 }; 117 118 static const UChar ID_SHORT[] = { 119 0x73, 0x68, 0x6F, 0x72, 0x74, 0 /* "short" */ 120 }; 121 static const UChar ID_MEDIUM[] = { 122 0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0 /* "medium" */ 123 }; 124 static const UChar ID_LONG[] = { 125 0x6C, 0x6F, 0x6E, 0x67, 0 /* "long" */ 126 }; 127 static const UChar ID_FULL[] = { 128 0x66, 0x75, 0x6C, 0x6C, 0 /* "full" */ 129 }; 130 131 // DateFormat modifier list, default, short, medium, long or full 132 static const UChar * const DATE_STYLE_IDS[] = { 133 ID_EMPTY, 134 ID_SHORT, 135 ID_MEDIUM, 136 ID_LONG, 137 ID_FULL, 138 NULL, 139 }; 140 141 static const icu::DateFormat::EStyle DATE_STYLES[] = { 142 icu::DateFormat::kDefault, 143 icu::DateFormat::kShort, 144 icu::DateFormat::kMedium, 145 icu::DateFormat::kLong, 146 icu::DateFormat::kFull, 147 }; 148 149 static const int32_t DEFAULT_INITIAL_CAPACITY = 10; 150 151 static const UChar NULL_STRING[] = { 152 0x6E, 0x75, 0x6C, 0x6C, 0 // "null" 153 }; 154 155 static const UChar OTHER_STRING[] = { 156 0x6F, 0x74, 0x68, 0x65, 0x72, 0 // "other" 157 }; 158 159 U_CDECL_BEGIN 160 static UBool U_CALLCONV equalFormatsForHash(const UHashTok key1, 161 const UHashTok key2) { 162 return icu::MessageFormat::equalFormats(key1.pointer, key2.pointer); 163 } 164 165 U_CDECL_END 166 167 U_NAMESPACE_BEGIN 168 169 // ------------------------------------- 170 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MessageFormat) 171 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FormatNameEnumeration) 172 173 //-------------------------------------------------------------------- 174 175 /** 176 * Convert an integer value to a string and append the result to 177 * the given UnicodeString. 178 */ 179 static UnicodeString& itos(int32_t i, UnicodeString& appendTo) { 180 UChar temp[16]; 181 uprv_itou(temp,16,i,10,0); // 10 == radix 182 appendTo.append(temp, -1); 183 return appendTo; 184 } 185 186 187 // AppendableWrapper: encapsulates the result of formatting, keeping track 188 // of the string and its length. 189 class AppendableWrapper : public UMemory { 190 public: 191 AppendableWrapper(Appendable& appendable) : app(appendable), len(0) { 192 } 193 void append(const UnicodeString& s) { 194 app.appendString(s.getBuffer(), s.length()); 195 len += s.length(); 196 } 197 void append(const UChar* s, const int32_t sLength) { 198 app.appendString(s, sLength); 199 len += sLength; 200 } 201 void append(const UnicodeString& s, int32_t start, int32_t length) { 202 append(s.tempSubString(start, length)); 203 } 204 void formatAndAppend(const Format* formatter, const Formattable& arg, UErrorCode& ec) { 205 UnicodeString s; 206 formatter->format(arg, s, ec); 207 if (U_SUCCESS(ec)) { 208 append(s); 209 } 210 } 211 void formatAndAppend(const Format* formatter, const Formattable& arg, 212 const UnicodeString &argString, UErrorCode& ec) { 213 if (!argString.isEmpty()) { 214 if (U_SUCCESS(ec)) { 215 append(argString); 216 } 217 } else { 218 formatAndAppend(formatter, arg, ec); 219 } 220 } 221 int32_t length() { 222 return len; 223 } 224 private: 225 Appendable& app; 226 int32_t len; 227 }; 228 229 230 // ------------------------------------- 231 // Creates a MessageFormat instance based on the pattern. 232 233 MessageFormat::MessageFormat(const UnicodeString& pattern, 234 UErrorCode& success) 235 : fLocale(Locale::getDefault()), // Uses the default locale 236 msgPattern(success), 237 formatAliases(NULL), 238 formatAliasesCapacity(0), 239 argTypes(NULL), 240 argTypeCount(0), 241 argTypeCapacity(0), 242 hasArgTypeConflicts(FALSE), 243 defaultNumberFormat(NULL), 244 defaultDateFormat(NULL), 245 cachedFormatters(NULL), 246 customFormatArgStarts(NULL), 247 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 248 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 249 { 250 setLocaleIDs(fLocale.getName(), fLocale.getName()); 251 applyPattern(pattern, success); 252 } 253 254 MessageFormat::MessageFormat(const UnicodeString& pattern, 255 const Locale& newLocale, 256 UErrorCode& success) 257 : fLocale(newLocale), 258 msgPattern(success), 259 formatAliases(NULL), 260 formatAliasesCapacity(0), 261 argTypes(NULL), 262 argTypeCount(0), 263 argTypeCapacity(0), 264 hasArgTypeConflicts(FALSE), 265 defaultNumberFormat(NULL), 266 defaultDateFormat(NULL), 267 cachedFormatters(NULL), 268 customFormatArgStarts(NULL), 269 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 270 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 271 { 272 setLocaleIDs(fLocale.getName(), fLocale.getName()); 273 applyPattern(pattern, success); 274 } 275 276 MessageFormat::MessageFormat(const UnicodeString& pattern, 277 const Locale& newLocale, 278 UParseError& parseError, 279 UErrorCode& success) 280 : fLocale(newLocale), 281 msgPattern(success), 282 formatAliases(NULL), 283 formatAliasesCapacity(0), 284 argTypes(NULL), 285 argTypeCount(0), 286 argTypeCapacity(0), 287 hasArgTypeConflicts(FALSE), 288 defaultNumberFormat(NULL), 289 defaultDateFormat(NULL), 290 cachedFormatters(NULL), 291 customFormatArgStarts(NULL), 292 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 293 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 294 { 295 setLocaleIDs(fLocale.getName(), fLocale.getName()); 296 applyPattern(pattern, parseError, success); 297 } 298 299 MessageFormat::MessageFormat(const MessageFormat& that) 300 : 301 Format(that), 302 fLocale(that.fLocale), 303 msgPattern(that.msgPattern), 304 formatAliases(NULL), 305 formatAliasesCapacity(0), 306 argTypes(NULL), 307 argTypeCount(0), 308 argTypeCapacity(0), 309 hasArgTypeConflicts(that.hasArgTypeConflicts), 310 defaultNumberFormat(NULL), 311 defaultDateFormat(NULL), 312 cachedFormatters(NULL), 313 customFormatArgStarts(NULL), 314 pluralProvider(*this, UPLURAL_TYPE_CARDINAL), 315 ordinalProvider(*this, UPLURAL_TYPE_ORDINAL) 316 { 317 // This will take care of creating the hash tables (since they are NULL). 318 UErrorCode ec = U_ZERO_ERROR; 319 copyObjects(that, ec); 320 if (U_FAILURE(ec)) { 321 resetPattern(); 322 } 323 } 324 325 MessageFormat::~MessageFormat() 326 { 327 uhash_close(cachedFormatters); 328 uhash_close(customFormatArgStarts); 329 330 uprv_free(argTypes); 331 uprv_free(formatAliases); 332 delete defaultNumberFormat; 333 delete defaultDateFormat; 334 } 335 336 //-------------------------------------------------------------------- 337 // Variable-size array management 338 339 /** 340 * Allocate argTypes[] to at least the given capacity and return 341 * TRUE if successful. If not, leave argTypes[] unchanged. 342 * 343 * If argTypes is NULL, allocate it. If it is not NULL, enlarge it 344 * if necessary to be at least as large as specified. 345 */ 346 UBool MessageFormat::allocateArgTypes(int32_t capacity, UErrorCode& status) { 347 if (U_FAILURE(status)) { 348 return FALSE; 349 } 350 if (argTypeCapacity >= capacity) { 351 return TRUE; 352 } 353 if (capacity < DEFAULT_INITIAL_CAPACITY) { 354 capacity = DEFAULT_INITIAL_CAPACITY; 355 } else if (capacity < 2*argTypeCapacity) { 356 capacity = 2*argTypeCapacity; 357 } 358 Formattable::Type* a = (Formattable::Type*) 359 uprv_realloc(argTypes, sizeof(*argTypes) * capacity); 360 if (a == NULL) { 361 status = U_MEMORY_ALLOCATION_ERROR; 362 return FALSE; 363 } 364 argTypes = a; 365 argTypeCapacity = capacity; 366 return TRUE; 367 } 368 369 // ------------------------------------- 370 // assignment operator 371 372 const MessageFormat& 373 MessageFormat::operator=(const MessageFormat& that) 374 { 375 if (this != &that) { 376 // Calls the super class for assignment first. 377 Format::operator=(that); 378 379 setLocale(that.fLocale); 380 msgPattern = that.msgPattern; 381 hasArgTypeConflicts = that.hasArgTypeConflicts; 382 383 UErrorCode ec = U_ZERO_ERROR; 384 copyObjects(that, ec); 385 if (U_FAILURE(ec)) { 386 resetPattern(); 387 } 388 } 389 return *this; 390 } 391 392 UBool 393 MessageFormat::operator==(const Format& rhs) const 394 { 395 if (this == &rhs) return TRUE; 396 397 MessageFormat& that = (MessageFormat&)rhs; 398 399 // Check class ID before checking MessageFormat members 400 if (!Format::operator==(rhs) || 401 msgPattern != that.msgPattern || 402 fLocale != that.fLocale) { 403 return FALSE; 404 } 405 406 // Compare hashtables. 407 if ((customFormatArgStarts == NULL) != (that.customFormatArgStarts == NULL)) { 408 return FALSE; 409 } 410 if (customFormatArgStarts == NULL) { 411 return TRUE; 412 } 413 414 UErrorCode ec = U_ZERO_ERROR; 415 const int32_t count = uhash_count(customFormatArgStarts); 416 const int32_t rhs_count = uhash_count(that.customFormatArgStarts); 417 if (count != rhs_count) { 418 return FALSE; 419 } 420 int32_t idx = 0, rhs_idx = 0, pos = UHASH_FIRST, rhs_pos = UHASH_FIRST; 421 for (; idx < count && rhs_idx < rhs_count && U_SUCCESS(ec); ++idx, ++rhs_idx) { 422 const UHashElement* cur = uhash_nextElement(customFormatArgStarts, &pos); 423 const UHashElement* rhs_cur = uhash_nextElement(that.customFormatArgStarts, &rhs_pos); 424 if (cur->key.integer != rhs_cur->key.integer) { 425 return FALSE; 426 } 427 const Format* format = (const Format*)uhash_iget(cachedFormatters, cur->key.integer); 428 const Format* rhs_format = (const Format*)uhash_iget(that.cachedFormatters, rhs_cur->key.integer); 429 if (*format != *rhs_format) { 430 return FALSE; 431 } 432 } 433 return TRUE; 434 } 435 436 // ------------------------------------- 437 // Creates a copy of this MessageFormat, the caller owns the copy. 438 439 Format* 440 MessageFormat::clone() const 441 { 442 return new MessageFormat(*this); 443 } 444 445 // ------------------------------------- 446 // Sets the locale of this MessageFormat object to theLocale. 447 448 void 449 MessageFormat::setLocale(const Locale& theLocale) 450 { 451 if (fLocale != theLocale) { 452 delete defaultNumberFormat; 453 defaultNumberFormat = NULL; 454 delete defaultDateFormat; 455 defaultDateFormat = NULL; 456 fLocale = theLocale; 457 setLocaleIDs(fLocale.getName(), fLocale.getName()); 458 pluralProvider.reset(); 459 ordinalProvider.reset(); 460 } 461 } 462 463 // ------------------------------------- 464 // Gets the locale of this MessageFormat object. 465 466 const Locale& 467 MessageFormat::getLocale() const 468 { 469 return fLocale; 470 } 471 472 void 473 MessageFormat::applyPattern(const UnicodeString& newPattern, 474 UErrorCode& status) 475 { 476 UParseError parseError; 477 applyPattern(newPattern,parseError,status); 478 } 479 480 481 // ------------------------------------- 482 // Applies the new pattern and returns an error if the pattern 483 // is not correct. 484 void 485 MessageFormat::applyPattern(const UnicodeString& pattern, 486 UParseError& parseError, 487 UErrorCode& ec) 488 { 489 if(U_FAILURE(ec)) { 490 return; 491 } 492 msgPattern.parse(pattern, &parseError, ec); 493 cacheExplicitFormats(ec); 494 495 if (U_FAILURE(ec)) { 496 resetPattern(); 497 } 498 } 499 500 void MessageFormat::resetPattern() { 501 msgPattern.clear(); 502 uhash_close(cachedFormatters); 503 cachedFormatters = NULL; 504 uhash_close(customFormatArgStarts); 505 customFormatArgStarts = NULL; 506 argTypeCount = 0; 507 hasArgTypeConflicts = FALSE; 508 } 509 510 void 511 MessageFormat::applyPattern(const UnicodeString& pattern, 512 UMessagePatternApostropheMode aposMode, 513 UParseError* parseError, 514 UErrorCode& status) { 515 if (aposMode != msgPattern.getApostropheMode()) { 516 msgPattern.clearPatternAndSetApostropheMode(aposMode); 517 } 518 applyPattern(pattern, *parseError, status); 519 } 520 521 // ------------------------------------- 522 // Converts this MessageFormat instance to a pattern. 523 524 UnicodeString& 525 MessageFormat::toPattern(UnicodeString& appendTo) const { 526 if ((customFormatArgStarts != NULL && 0 != uhash_count(customFormatArgStarts)) || 527 0 == msgPattern.countParts() 528 ) { 529 appendTo.setToBogus(); 530 return appendTo; 531 } 532 return appendTo.append(msgPattern.getPatternString()); 533 } 534 535 int32_t MessageFormat::nextTopLevelArgStart(int32_t partIndex) const { 536 if (partIndex != 0) { 537 partIndex = msgPattern.getLimitPartIndex(partIndex); 538 } 539 for (;;) { 540 UMessagePatternPartType type = msgPattern.getPartType(++partIndex); 541 if (type == UMSGPAT_PART_TYPE_ARG_START) { 542 return partIndex; 543 } 544 if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) { 545 return -1; 546 } 547 } 548 } 549 550 void MessageFormat::setArgStartFormat(int32_t argStart, 551 Format* formatter, 552 UErrorCode& status) { 553 if (U_FAILURE(status)) { 554 delete formatter; 555 return; 556 } 557 if (cachedFormatters == NULL) { 558 cachedFormatters=uhash_open(uhash_hashLong, uhash_compareLong, 559 equalFormatsForHash, &status); 560 if (U_FAILURE(status)) { 561 delete formatter; 562 return; 563 } 564 uhash_setValueDeleter(cachedFormatters, uprv_deleteUObject); 565 } 566 if (formatter == NULL) { 567 formatter = new DummyFormat(); 568 } 569 uhash_iput(cachedFormatters, argStart, formatter, &status); 570 } 571 572 573 UBool MessageFormat::argNameMatches(int32_t partIndex, const UnicodeString& argName, int32_t argNumber) { 574 const MessagePattern::Part& part = msgPattern.getPart(partIndex); 575 return part.getType() == UMSGPAT_PART_TYPE_ARG_NAME ? 576 msgPattern.partSubstringMatches(part, argName) : 577 part.getValue() == argNumber; // ARG_NUMBER 578 } 579 580 // Sets a custom formatter for a MessagePattern ARG_START part index. 581 // "Custom" formatters are provided by the user via setFormat() or similar APIs. 582 void MessageFormat::setCustomArgStartFormat(int32_t argStart, 583 Format* formatter, 584 UErrorCode& status) { 585 setArgStartFormat(argStart, formatter, status); 586 if (customFormatArgStarts == NULL) { 587 customFormatArgStarts=uhash_open(uhash_hashLong, uhash_compareLong, 588 NULL, &status); 589 } 590 uhash_iputi(customFormatArgStarts, argStart, 1, &status); 591 } 592 593 Format* MessageFormat::getCachedFormatter(int32_t argumentNumber) const { 594 if (cachedFormatters == NULL) { 595 return NULL; 596 } 597 void* ptr = uhash_iget(cachedFormatters, argumentNumber); 598 if (ptr != NULL && dynamic_cast<DummyFormat*>((Format*)ptr) == NULL) { 599 return (Format*) ptr; 600 } else { 601 // Not cached, or a DummyFormat representing setFormat(NULL). 602 return NULL; 603 } 604 } 605 606 // ------------------------------------- 607 // Adopts the new formats array and updates the array count. 608 // This MessageFormat instance owns the new formats. 609 void 610 MessageFormat::adoptFormats(Format** newFormats, 611 int32_t count) { 612 if (newFormats == NULL || count < 0) { 613 return; 614 } 615 // Throw away any cached formatters. 616 if (cachedFormatters != NULL) { 617 uhash_removeAll(cachedFormatters); 618 } 619 if (customFormatArgStarts != NULL) { 620 uhash_removeAll(customFormatArgStarts); 621 } 622 623 int32_t formatNumber = 0; 624 UErrorCode status = U_ZERO_ERROR; 625 for (int32_t partIndex = 0; 626 formatNumber < count && U_SUCCESS(status) && 627 (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 628 setCustomArgStartFormat(partIndex, newFormats[formatNumber], status); 629 ++formatNumber; 630 } 631 // Delete those that didn't get used (if any). 632 for (; formatNumber < count; ++formatNumber) { 633 delete newFormats[formatNumber]; 634 } 635 636 } 637 638 // ------------------------------------- 639 // Sets the new formats array and updates the array count. 640 // This MessageFormat instance maks a copy of the new formats. 641 642 void 643 MessageFormat::setFormats(const Format** newFormats, 644 int32_t count) { 645 if (newFormats == NULL || count < 0) { 646 return; 647 } 648 // Throw away any cached formatters. 649 if (cachedFormatters != NULL) { 650 uhash_removeAll(cachedFormatters); 651 } 652 if (customFormatArgStarts != NULL) { 653 uhash_removeAll(customFormatArgStarts); 654 } 655 656 UErrorCode status = U_ZERO_ERROR; 657 int32_t formatNumber = 0; 658 for (int32_t partIndex = 0; 659 formatNumber < count && U_SUCCESS(status) && (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 660 Format* newFormat = NULL; 661 if (newFormats[formatNumber] != NULL) { 662 newFormat = newFormats[formatNumber]->clone(); 663 if (newFormat == NULL) { 664 status = U_MEMORY_ALLOCATION_ERROR; 665 } 666 } 667 setCustomArgStartFormat(partIndex, newFormat, status); 668 ++formatNumber; 669 } 670 if (U_FAILURE(status)) { 671 resetPattern(); 672 } 673 } 674 675 // ------------------------------------- 676 // Adopt a single format by format number. 677 // Do nothing if the format number is not less than the array count. 678 679 void 680 MessageFormat::adoptFormat(int32_t n, Format *newFormat) { 681 LocalPointer<Format> p(newFormat); 682 if (n >= 0) { 683 int32_t formatNumber = 0; 684 for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 685 if (n == formatNumber) { 686 UErrorCode status = U_ZERO_ERROR; 687 setCustomArgStartFormat(partIndex, p.orphan(), status); 688 return; 689 } 690 ++formatNumber; 691 } 692 } 693 } 694 695 // ------------------------------------- 696 // Adopt a single format by format name. 697 // Do nothing if there is no match of formatName. 698 void 699 MessageFormat::adoptFormat(const UnicodeString& formatName, 700 Format* formatToAdopt, 701 UErrorCode& status) { 702 LocalPointer<Format> p(formatToAdopt); 703 if (U_FAILURE(status)) { 704 return; 705 } 706 int32_t argNumber = MessagePattern::validateArgumentName(formatName); 707 if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) { 708 status = U_ILLEGAL_ARGUMENT_ERROR; 709 return; 710 } 711 for (int32_t partIndex = 0; 712 (partIndex = nextTopLevelArgStart(partIndex)) >= 0 && U_SUCCESS(status); 713 ) { 714 if (argNameMatches(partIndex + 1, formatName, argNumber)) { 715 Format* f; 716 if (p.isValid()) { 717 f = p.orphan(); 718 } else if (formatToAdopt == NULL) { 719 f = NULL; 720 } else { 721 f = formatToAdopt->clone(); 722 if (f == NULL) { 723 status = U_MEMORY_ALLOCATION_ERROR; 724 return; 725 } 726 } 727 setCustomArgStartFormat(partIndex, f, status); 728 } 729 } 730 } 731 732 // ------------------------------------- 733 // Set a single format. 734 // Do nothing if the variable is not less than the array count. 735 void 736 MessageFormat::setFormat(int32_t n, const Format& newFormat) { 737 738 if (n >= 0) { 739 int32_t formatNumber = 0; 740 for (int32_t partIndex = 0; 741 (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 742 if (n == formatNumber) { 743 Format* new_format = newFormat.clone(); 744 if (new_format) { 745 UErrorCode status = U_ZERO_ERROR; 746 setCustomArgStartFormat(partIndex, new_format, status); 747 } 748 return; 749 } 750 ++formatNumber; 751 } 752 } 753 } 754 755 // ------------------------------------- 756 // Get a single format by format name. 757 // Do nothing if the variable is not less than the array count. 758 Format * 759 MessageFormat::getFormat(const UnicodeString& formatName, UErrorCode& status) { 760 if (U_FAILURE(status) || cachedFormatters == NULL) return NULL; 761 762 int32_t argNumber = MessagePattern::validateArgumentName(formatName); 763 if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) { 764 status = U_ILLEGAL_ARGUMENT_ERROR; 765 return NULL; 766 } 767 for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) { 768 if (argNameMatches(partIndex + 1, formatName, argNumber)) { 769 return getCachedFormatter(partIndex); 770 } 771 } 772 return NULL; 773 } 774 775 // ------------------------------------- 776 // Set a single format by format name 777 // Do nothing if the variable is not less than the array count. 778 void 779 MessageFormat::setFormat(const UnicodeString& formatName, 780 const Format& newFormat, 781 UErrorCode& status) { 782 if (U_FAILURE(status)) return; 783 784 int32_t argNumber = MessagePattern::validateArgumentName(formatName); 785 if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) { 786 status = U_ILLEGAL_ARGUMENT_ERROR; 787 return; 788 } 789 for (int32_t partIndex = 0; 790 (partIndex = nextTopLevelArgStart(partIndex)) >= 0 && U_SUCCESS(status); 791 ) { 792 if (argNameMatches(partIndex + 1, formatName, argNumber)) { 793 Format* new_format = newFormat.clone(); 794 if (new_format == NULL) { 795 status = U_MEMORY_ALLOCATION_ERROR; 796 return; 797 } 798 setCustomArgStartFormat(partIndex, new_format, status); 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)) != 0) { 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 = UHASH_FIRST; 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 = UHASH_FIRST; 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 or skeleton 1705 int32_t i = 0; 1706 for (; PatternProps::isWhiteSpace(style.charAt(i)); i++); 1707 if (style.compare(i, 2, u"::", 0, 2) == 0) { 1708 // Skeleton 1709 UnicodeString skeleton = style.tempSubString(i + 2); 1710 fmt = number::NumberFormatter::forSkeleton(skeleton, ec).locale(fLocale).toFormat(ec); 1711 } else { 1712 // Pattern 1713 fmt = NumberFormat::createInstance(fLocale, ec); 1714 if (fmt) { 1715 auto* decfmt = dynamic_cast<DecimalFormat*>(fmt); 1716 if (decfmt != nullptr) { 1717 decfmt->applyPattern(style, parseError, ec); 1718 } 1719 } 1720 } 1721 break; 1722 } 1723 break; 1724 1725 case 1: // date 1726 case 2: // time 1727 formattableType = Formattable::kDate; 1728 styleID = findKeyword(style, DATE_STYLE_IDS); 1729 date_style = (styleID >= 0) ? DATE_STYLES[styleID] : DateFormat::kDefault; 1730 1731 if (typeID == 1) { 1732 fmt = DateFormat::createDateInstance(date_style, fLocale); 1733 } else { 1734 fmt = DateFormat::createTimeInstance(date_style, fLocale); 1735 } 1736 1737 if (styleID < 0 && fmt != NULL) { 1738 SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(fmt); 1739 if (sdtfmt != NULL) { 1740 sdtfmt->applyPattern(style); 1741 } 1742 } 1743 break; 1744 1745 case 3: // spellout 1746 formattableType = Formattable::kDouble; 1747 fmt = makeRBNF(URBNF_SPELLOUT, fLocale, style, ec); 1748 break; 1749 case 4: // ordinal 1750 formattableType = Formattable::kDouble; 1751 fmt = makeRBNF(URBNF_ORDINAL, fLocale, style, ec); 1752 break; 1753 case 5: // duration 1754 formattableType = Formattable::kDouble; 1755 fmt = makeRBNF(URBNF_DURATION, fLocale, style, ec); 1756 break; 1757 default: 1758 formattableType = Formattable::kString; 1759 ec = U_ILLEGAL_ARGUMENT_ERROR; 1760 break; 1761 } 1762 1763 return fmt; 1764 } 1765 1766 1767 //------------------------------------- 1768 // Finds the string, s, in the string array, list. 1769 int32_t MessageFormat::findKeyword(const UnicodeString& s, 1770 const UChar * const *list) 1771 { 1772 if (s.isEmpty()) { 1773 return 0; // default 1774 } 1775 1776 int32_t length = s.length(); 1777 const UChar *ps = PatternProps::trimWhiteSpace(s.getBuffer(), length); 1778 UnicodeString buffer(FALSE, ps, length); 1779 // Trims the space characters and turns all characters 1780 // in s to lower case. 1781 buffer.toLower(""); 1782 for (int32_t i = 0; list[i]; ++i) { 1783 if (!buffer.compare(list[i], u_strlen(list[i]))) { 1784 return i; 1785 } 1786 } 1787 return -1; 1788 } 1789 1790 /** 1791 * Convenience method that ought to be in NumberFormat 1792 */ 1793 NumberFormat* 1794 MessageFormat::createIntegerFormat(const Locale& locale, UErrorCode& status) const { 1795 NumberFormat *temp = NumberFormat::createInstance(locale, status); 1796 DecimalFormat *temp2; 1797 if (temp != NULL && (temp2 = dynamic_cast<DecimalFormat*>(temp)) != NULL) { 1798 temp2->setMaximumFractionDigits(0); 1799 temp2->setDecimalSeparatorAlwaysShown(FALSE); 1800 temp2->setParseIntegerOnly(TRUE); 1801 } 1802 1803 return temp; 1804 } 1805 1806 /** 1807 * Return the default number format. Used to format a numeric 1808 * argument when subformats[i].format is NULL. Returns NULL 1809 * on failure. 1810 * 1811 * Semantically const but may modify *this. 1812 */ 1813 const NumberFormat* MessageFormat::getDefaultNumberFormat(UErrorCode& ec) const { 1814 if (defaultNumberFormat == NULL) { 1815 MessageFormat* t = (MessageFormat*) this; 1816 t->defaultNumberFormat = NumberFormat::createInstance(fLocale, ec); 1817 if (U_FAILURE(ec)) { 1818 delete t->defaultNumberFormat; 1819 t->defaultNumberFormat = NULL; 1820 } else if (t->defaultNumberFormat == NULL) { 1821 ec = U_MEMORY_ALLOCATION_ERROR; 1822 } 1823 } 1824 return defaultNumberFormat; 1825 } 1826 1827 /** 1828 * Return the default date format. Used to format a date 1829 * argument when subformats[i].format is NULL. Returns NULL 1830 * on failure. 1831 * 1832 * Semantically const but may modify *this. 1833 */ 1834 const DateFormat* MessageFormat::getDefaultDateFormat(UErrorCode& ec) const { 1835 if (defaultDateFormat == NULL) { 1836 MessageFormat* t = (MessageFormat*) this; 1837 t->defaultDateFormat = DateFormat::createDateTimeInstance(DateFormat::kShort, DateFormat::kShort, fLocale); 1838 if (t->defaultDateFormat == NULL) { 1839 ec = U_MEMORY_ALLOCATION_ERROR; 1840 } 1841 } 1842 return defaultDateFormat; 1843 } 1844 1845 UBool 1846 MessageFormat::usesNamedArguments() const { 1847 return msgPattern.hasNamedArguments(); 1848 } 1849 1850 int32_t 1851 MessageFormat::getArgTypeCount() const { 1852 return argTypeCount; 1853 } 1854 1855 UBool MessageFormat::equalFormats(const void* left, const void* right) { 1856 return *(const Format*)left==*(const Format*)right; 1857 } 1858 1859 1860 UBool MessageFormat::DummyFormat::operator==(const Format&) const { 1861 return TRUE; 1862 } 1863 1864 Format* MessageFormat::DummyFormat::clone() const { 1865 return new DummyFormat(); 1866 } 1867 1868 UnicodeString& MessageFormat::DummyFormat::format(const Formattable&, 1869 UnicodeString& appendTo, 1870 UErrorCode& status) const { 1871 if (U_SUCCESS(status)) { 1872 status = U_UNSUPPORTED_ERROR; 1873 } 1874 return appendTo; 1875 } 1876 1877 UnicodeString& MessageFormat::DummyFormat::format(const Formattable&, 1878 UnicodeString& appendTo, 1879 FieldPosition&, 1880 UErrorCode& status) const { 1881 if (U_SUCCESS(status)) { 1882 status = U_UNSUPPORTED_ERROR; 1883 } 1884 return appendTo; 1885 } 1886 1887 UnicodeString& MessageFormat::DummyFormat::format(const Formattable&, 1888 UnicodeString& appendTo, 1889 FieldPositionIterator*, 1890 UErrorCode& status) const { 1891 if (U_SUCCESS(status)) { 1892 status = U_UNSUPPORTED_ERROR; 1893 } 1894 return appendTo; 1895 } 1896 1897 void MessageFormat::DummyFormat::parseObject(const UnicodeString&, 1898 Formattable&, 1899 ParsePosition& ) const { 1900 } 1901 1902 1903 FormatNameEnumeration::FormatNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) { 1904 pos=0; 1905 fFormatNames = fNameList; 1906 } 1907 1908 const UnicodeString* 1909 FormatNameEnumeration::snext(UErrorCode& status) { 1910 if (U_SUCCESS(status) && pos < fFormatNames->size()) { 1911 return (const UnicodeString*)fFormatNames->elementAt(pos++); 1912 } 1913 return NULL; 1914 } 1915 1916 void 1917 FormatNameEnumeration::reset(UErrorCode& /*status*/) { 1918 pos=0; 1919 } 1920 1921 int32_t 1922 FormatNameEnumeration::count(UErrorCode& /*status*/) const { 1923 return (fFormatNames==NULL) ? 0 : fFormatNames->size(); 1924 } 1925 1926 FormatNameEnumeration::~FormatNameEnumeration() { 1927 delete fFormatNames; 1928 } 1929 1930 MessageFormat::PluralSelectorProvider::PluralSelectorProvider(const MessageFormat &mf, UPluralType t) 1931 : msgFormat(mf), rules(NULL), type(t) { 1932 } 1933 1934 MessageFormat::PluralSelectorProvider::~PluralSelectorProvider() { 1935 delete rules; 1936 } 1937 1938 UnicodeString MessageFormat::PluralSelectorProvider::select(void *ctx, double number, 1939 UErrorCode& ec) const { 1940 if (U_FAILURE(ec)) { 1941 return UnicodeString(FALSE, OTHER_STRING, 5); 1942 } 1943 MessageFormat::PluralSelectorProvider* t = const_cast<MessageFormat::PluralSelectorProvider*>(this); 1944 if(rules == NULL) { 1945 t->rules = PluralRules::forLocale(msgFormat.fLocale, type, ec); 1946 if (U_FAILURE(ec)) { 1947 return UnicodeString(FALSE, OTHER_STRING, 5); 1948 } 1949 } 1950 // Select a sub-message according to how the number is formatted, 1951 // which is specified in the selected sub-message. 1952 // We avoid this circle by looking at how 1953 // the number is formatted in the "other" sub-message 1954 // which must always be present and usually contains the number. 1955 // Message authors should be consistent across sub-messages. 1956 PluralSelectorContext &context = *static_cast<PluralSelectorContext *>(ctx); 1957 int32_t otherIndex = msgFormat.findOtherSubMessage(context.startIndex); 1958 context.numberArgIndex = msgFormat.findFirstPluralNumberArg(otherIndex, context.argName); 1959 if(context.numberArgIndex > 0 && msgFormat.cachedFormatters != NULL) { 1960 context.formatter = 1961 (const Format*)uhash_iget(msgFormat.cachedFormatters, context.numberArgIndex); 1962 } 1963 if(context.formatter == NULL) { 1964 context.formatter = msgFormat.getDefaultNumberFormat(ec); 1965 context.forReplaceNumber = TRUE; 1966 } 1967 if (context.number.getDouble(ec) != number) { 1968 ec = U_INTERNAL_PROGRAM_ERROR; 1969 return UnicodeString(FALSE, OTHER_STRING, 5); 1970 } 1971 context.formatter->format(context.number, context.numberString, ec); 1972 auto* decFmt = dynamic_cast<const DecimalFormat *>(context.formatter); 1973 if(decFmt != NULL) { 1974 number::impl::DecimalQuantity dq; 1975 decFmt->formatToDecimalQuantity(context.number, dq, ec); 1976 if (U_FAILURE(ec)) { 1977 return UnicodeString(FALSE, OTHER_STRING, 5); 1978 } 1979 return rules->select(dq); 1980 } else { 1981 return rules->select(number); 1982 } 1983 } 1984 1985 void MessageFormat::PluralSelectorProvider::reset() { 1986 delete rules; 1987 rules = NULL; 1988 } 1989 1990 1991 U_NAMESPACE_END 1992 1993 #endif /* #if !UCONFIG_NO_FORMATTING */ 1994 1995 //eof 1996