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