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