tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

msgfmt.cpp (72473B)


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