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