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