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