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