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