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