LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - msgfmt.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 932 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 92 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13