1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2010, 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/msgfmt.h"
27#include "unicode/decimfmt.h"
28#include "unicode/datefmt.h"
29#include "unicode/smpdtfmt.h"
30#include "unicode/choicfmt.h"
31#include "unicode/plurfmt.h"
32#include "unicode/selfmt.h"
33#include "unicode/ustring.h"
34#include "unicode/ucnv_err.h"
35#include "unicode/uchar.h"
36#include "unicode/umsg.h"
37#include "unicode/rbnf.h"
38#include "cmemory.h"
39#include "msgfmt_impl.h"
40#include "util.h"
41#include "uassert.h"
42#include "ustrfmt.h"
43#include "uvector.h"
44
45// *****************************************************************************
46// class MessageFormat
47// *****************************************************************************
48
49#define COMMA             ((UChar)0x002C)
50#define SINGLE_QUOTE      ((UChar)0x0027)
51#define LEFT_CURLY_BRACE  ((UChar)0x007B)
52#define RIGHT_CURLY_BRACE ((UChar)0x007D)
53
54//---------------------------------------
55// static data
56
57static const UChar ID_EMPTY[]     = {
58    0 /* empty string, used for default so that null can mark end of list */
59};
60
61static const UChar ID_NUMBER[]    = {
62    0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0  /* "number" */
63};
64static const UChar ID_DATE[]      = {
65    0x64, 0x61, 0x74, 0x65, 0              /* "date" */
66};
67static const UChar ID_TIME[]      = {
68    0x74, 0x69, 0x6D, 0x65, 0              /* "time" */
69};
70static const UChar ID_CHOICE[]    = {
71    0x63, 0x68, 0x6F, 0x69, 0x63, 0x65, 0  /* "choice" */
72};
73static const UChar ID_SPELLOUT[]  = {
74    0x73, 0x70, 0x65, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0 /* "spellout" */
75};
76static const UChar ID_ORDINAL[]   = {
77    0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0 /* "ordinal" */
78};
79static const UChar ID_DURATION[]  = {
80    0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0 /* "duration" */
81};
82static const UChar ID_PLURAL[]  = {
83    0x70, 0x6c, 0x75, 0x72, 0x61, 0x6c, 0  /* "plural" */
84};
85static const UChar ID_SELECT[]  = {
86    0x73, 0x65, 0x6C, 0x65, 0x63, 0x74, 0  /* "select" */
87};
88
89// MessageFormat Type List  Number, Date, Time or Choice
90static const UChar * const TYPE_IDS[] = {
91    ID_EMPTY,
92    ID_NUMBER,
93    ID_DATE,
94    ID_TIME,
95    ID_CHOICE,
96    ID_SPELLOUT,
97    ID_ORDINAL,
98    ID_DURATION,
99    ID_PLURAL,
100    ID_SELECT,
101    NULL,
102};
103
104static const UChar ID_CURRENCY[]  = {
105    0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x63, 0x79, 0  /* "currency" */
106};
107static const UChar ID_PERCENT[]   = {
108    0x70, 0x65, 0x72, 0x63, 0x65, 0x6E, 0x74, 0        /* "percent" */
109};
110static const UChar ID_INTEGER[]   = {
111    0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0        /* "integer" */
112};
113
114// NumberFormat modifier list, default, currency, percent or integer
115static const UChar * const NUMBER_STYLE_IDS[] = {
116    ID_EMPTY,
117    ID_CURRENCY,
118    ID_PERCENT,
119    ID_INTEGER,
120    NULL,
121};
122
123static const UChar ID_SHORT[]     = {
124    0x73, 0x68, 0x6F, 0x72, 0x74, 0        /* "short" */
125};
126static const UChar ID_MEDIUM[]    = {
127    0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0  /* "medium" */
128};
129static const UChar ID_LONG[]      = {
130    0x6C, 0x6F, 0x6E, 0x67, 0              /* "long" */
131};
132static const UChar ID_FULL[]      = {
133    0x66, 0x75, 0x6C, 0x6C, 0              /* "full" */
134};
135
136// DateFormat modifier list, default, short, medium, long or full
137static const UChar * const DATE_STYLE_IDS[] = {
138    ID_EMPTY,
139    ID_SHORT,
140    ID_MEDIUM,
141    ID_LONG,
142    ID_FULL,
143    NULL,
144};
145
146static const U_NAMESPACE_QUALIFIER DateFormat::EStyle DATE_STYLES[] = {
147    U_NAMESPACE_QUALIFIER DateFormat::kDefault,
148    U_NAMESPACE_QUALIFIER DateFormat::kShort,
149    U_NAMESPACE_QUALIFIER DateFormat::kMedium,
150    U_NAMESPACE_QUALIFIER DateFormat::kLong,
151    U_NAMESPACE_QUALIFIER DateFormat::kFull,
152};
153
154static const int32_t DEFAULT_INITIAL_CAPACITY = 10;
155
156U_NAMESPACE_BEGIN
157
158// -------------------------------------
159UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MessageFormat)
160UOBJECT_DEFINE_RTTI_IMPLEMENTATION(FormatNameEnumeration)
161
162//--------------------------------------------------------------------
163
164/**
165 * Convert a string to an unsigned decimal, ignoring rule whitespace.
166 * @return a non-negative number if successful, or a negative number
167 *         upon failure.
168 */
169static int32_t stou(const UnicodeString& string) {
170    int32_t n = 0;
171    int32_t count = 0;
172    UChar32 c;
173    for (int32_t i=0; i<string.length(); i+=U16_LENGTH(c)) {
174        c = string.char32At(i);
175        if (uprv_isRuleWhiteSpace(c)) {
176            continue;
177        }
178        int32_t d = u_digit(c, 10);
179        if (d < 0 || ++count > 10) {
180            return -1;
181        }
182        n = 10*n + d;
183    }
184    return n;
185}
186
187/**
188 * Convert an integer value to a string and append the result to
189 * the given UnicodeString.
190 */
191static UnicodeString& itos(int32_t i, UnicodeString& appendTo) {
192    UChar temp[16];
193    uprv_itou(temp,16,i,10,0); // 10 == radix
194    appendTo.append(temp);
195    return appendTo;
196}
197
198/*
199 * A structure representing one subformat of this MessageFormat.
200 * Each subformat has a Format object, an offset into the plain
201 * pattern text fPattern, and an argument number.  The argument
202 * number corresponds to the array of arguments to be formatted.
203 * @internal
204 */
205class MessageFormat::Subformat : public UMemory {
206public:
207    /**
208     * @internal
209     */
210    Format* format; // formatter
211    /**
212     * @internal
213     */
214    int32_t offset; // offset into fPattern
215    /**
216     * @internal
217     */
218    // TODO (claireho) or save the number to argName and use itos to convert to number.=> we need this number
219    int32_t argNum;    // 0-based argument number
220    /**
221     * @internal
222     */
223    UnicodeString* argName; // argument name or number
224
225    /**
226     * Clone that.format and assign it to this.format
227     * Do NOT delete this.format
228     * @internal
229     */
230    Subformat& operator=(const Subformat& that) {
231        if (this != &that) {
232            format = that.format ? that.format->clone() : NULL;
233            offset = that.offset;
234            argNum = that.argNum;
235            argName = (that.argNum==-1) ? new UnicodeString(*that.argName): NULL;
236        }
237        return *this;
238    }
239
240    /**
241     * @internal
242     */
243    UBool operator==(const Subformat& that) const {
244        // Do cheap comparisons first
245        return offset == that.offset &&
246               argNum == that.argNum &&
247               ((argName == that.argName) ||
248                (*argName == *that.argName)) &&
249               ((format == that.format) || // handles NULL
250                (*format == *that.format));
251    }
252
253    /**
254     * @internal
255     */
256    UBool operator!=(const Subformat& that) const {
257        return !operator==(that);
258    }
259};
260
261// -------------------------------------
262// Creates a MessageFormat instance based on the pattern.
263
264MessageFormat::MessageFormat(const UnicodeString& pattern,
265                             UErrorCode& success)
266: fLocale(Locale::getDefault()),  // Uses the default locale
267  formatAliases(NULL),
268  formatAliasesCapacity(0),
269  idStart(UCHAR_ID_START),
270  idContinue(UCHAR_ID_CONTINUE),
271  subformats(NULL),
272  subformatCount(0),
273  subformatCapacity(0),
274  argTypes(NULL),
275  argTypeCount(0),
276  argTypeCapacity(0),
277  isArgNumeric(TRUE),
278  defaultNumberFormat(NULL),
279  defaultDateFormat(NULL)
280{
281    if (!allocateSubformats(DEFAULT_INITIAL_CAPACITY) ||
282        !allocateArgTypes(DEFAULT_INITIAL_CAPACITY)) {
283        success = U_MEMORY_ALLOCATION_ERROR;
284        return;
285    }
286    applyPattern(pattern, success);
287    setLocaleIDs(fLocale.getName(), fLocale.getName());
288}
289
290MessageFormat::MessageFormat(const UnicodeString& pattern,
291                             const Locale& newLocale,
292                             UErrorCode& success)
293: fLocale(newLocale),
294  formatAliases(NULL),
295  formatAliasesCapacity(0),
296  idStart(UCHAR_ID_START),
297  idContinue(UCHAR_ID_CONTINUE),
298  subformats(NULL),
299  subformatCount(0),
300  subformatCapacity(0),
301  argTypes(NULL),
302  argTypeCount(0),
303  argTypeCapacity(0),
304  isArgNumeric(TRUE),
305  defaultNumberFormat(NULL),
306  defaultDateFormat(NULL)
307{
308    if (!allocateSubformats(DEFAULT_INITIAL_CAPACITY) ||
309        !allocateArgTypes(DEFAULT_INITIAL_CAPACITY)) {
310        success = U_MEMORY_ALLOCATION_ERROR;
311        return;
312    }
313    applyPattern(pattern, success);
314    setLocaleIDs(fLocale.getName(), fLocale.getName());
315}
316
317MessageFormat::MessageFormat(const UnicodeString& pattern,
318                             const Locale& newLocale,
319                             UParseError& parseError,
320                             UErrorCode& success)
321: fLocale(newLocale),
322  formatAliases(NULL),
323  formatAliasesCapacity(0),
324  idStart(UCHAR_ID_START),
325  idContinue(UCHAR_ID_CONTINUE),
326  subformats(NULL),
327  subformatCount(0),
328  subformatCapacity(0),
329  argTypes(NULL),
330  argTypeCount(0),
331  argTypeCapacity(0),
332  isArgNumeric(TRUE),
333  defaultNumberFormat(NULL),
334  defaultDateFormat(NULL)
335{
336    if (!allocateSubformats(DEFAULT_INITIAL_CAPACITY) ||
337        !allocateArgTypes(DEFAULT_INITIAL_CAPACITY)) {
338        success = U_MEMORY_ALLOCATION_ERROR;
339        return;
340    }
341    applyPattern(pattern, parseError, success);
342    setLocaleIDs(fLocale.getName(), fLocale.getName());
343}
344
345MessageFormat::MessageFormat(const MessageFormat& that)
346: Format(that),
347  formatAliases(NULL),
348  formatAliasesCapacity(0),
349  idStart(UCHAR_ID_START),
350  idContinue(UCHAR_ID_CONTINUE),
351  subformats(NULL),
352  subformatCount(0),
353  subformatCapacity(0),
354  argTypes(NULL),
355  argTypeCount(0),
356  argTypeCapacity(0),
357  isArgNumeric(TRUE),
358  defaultNumberFormat(NULL),
359  defaultDateFormat(NULL)
360{
361    *this = that;
362}
363
364MessageFormat::~MessageFormat()
365{
366    int32_t idx;
367    for (idx = 0; idx < subformatCount; idx++) {
368        delete subformats[idx].format;
369        delete subformats[idx].argName;
370    }
371    uprv_free(subformats);
372    subformats = NULL;
373    subformatCount = subformatCapacity = 0;
374
375    uprv_free(argTypes);
376    argTypes = NULL;
377    argTypeCount = argTypeCapacity = 0;
378
379    uprv_free(formatAliases);
380
381    delete defaultNumberFormat;
382    delete defaultDateFormat;
383}
384
385//--------------------------------------------------------------------
386// Variable-size array management
387
388/**
389 * Allocate subformats[] to at least the given capacity and return
390 * TRUE if successful.  If not, leave subformats[] unchanged.
391 *
392 * If subformats is NULL, allocate it.  If it is not NULL, enlarge it
393 * if necessary to be at least as large as specified.
394 */
395UBool MessageFormat::allocateSubformats(int32_t capacity) {
396    if (subformats == NULL) {
397        subformats = (Subformat*) uprv_malloc(sizeof(*subformats) * capacity);
398        subformatCapacity = capacity;
399        subformatCount = 0;
400        if (subformats == NULL) {
401            subformatCapacity = 0;
402            return FALSE;
403        }
404    } else if (subformatCapacity < capacity) {
405        if (capacity < 2*subformatCapacity) {
406            capacity = 2*subformatCapacity;
407        }
408        Subformat* a = (Subformat*)
409            uprv_realloc(subformats, sizeof(*subformats) * capacity);
410        if (a == NULL) {
411            return FALSE; // request failed
412        }
413        subformats = a;
414        subformatCapacity = capacity;
415    }
416    return TRUE;
417}
418
419/**
420 * Allocate argTypes[] to at least the given capacity and return
421 * TRUE if successful.  If not, leave argTypes[] unchanged.
422 *
423 * If argTypes is NULL, allocate it.  If it is not NULL, enlarge it
424 * if necessary to be at least as large as specified.
425 */
426UBool MessageFormat::allocateArgTypes(int32_t capacity) {
427    if (argTypes == NULL) {
428        argTypes = (Formattable::Type*) uprv_malloc(sizeof(*argTypes) * capacity);
429        argTypeCount = 0;
430        argTypeCapacity = capacity;
431        if (argTypes == NULL) {
432            argTypeCapacity = 0;
433            return FALSE;
434        }
435        for (int32_t i=0; i<capacity; ++i) {
436            argTypes[i] = Formattable::kString;
437        }
438    } else if (argTypeCapacity < capacity) {
439        if (capacity < 2*argTypeCapacity) {
440            capacity = 2*argTypeCapacity;
441        }
442        Formattable::Type* a = (Formattable::Type*)
443            uprv_realloc(argTypes, sizeof(*argTypes) * capacity);
444        if (a == NULL) {
445            return FALSE; // request failed
446        }
447        for (int32_t i=argTypeCapacity; i<capacity; ++i) {
448            a[i] = Formattable::kString;
449        }
450        argTypes = a;
451        argTypeCapacity = capacity;
452    }
453    return TRUE;
454}
455
456// -------------------------------------
457// assignment operator
458
459const MessageFormat&
460MessageFormat::operator=(const MessageFormat& that)
461{
462    // Reallocate the arrays BEFORE changing this object
463    if (this != &that &&
464        allocateSubformats(that.subformatCount) &&
465        allocateArgTypes(that.argTypeCount)) {
466
467        // Calls the super class for assignment first.
468        Format::operator=(that);
469
470        fPattern = that.fPattern;
471        setLocale(that.fLocale);
472        isArgNumeric = that.isArgNumeric;
473        int32_t j;
474        for (j=0; j<subformatCount; ++j) {
475            delete subformats[j].format;
476        }
477        subformatCount = 0;
478
479        for (j=0; j<that.subformatCount; ++j) {
480            // Subformat::operator= does NOT delete this.format
481            subformats[j] = that.subformats[j];
482        }
483        subformatCount = that.subformatCount;
484
485        for (j=0; j<that.argTypeCount; ++j) {
486            argTypes[j] = that.argTypes[j];
487        }
488        argTypeCount = that.argTypeCount;
489    }
490    return *this;
491}
492
493UBool
494MessageFormat::operator==(const Format& rhs) const
495{
496    if (this == &rhs) return TRUE;
497
498    MessageFormat& that = (MessageFormat&)rhs;
499
500    // Check class ID before checking MessageFormat members
501    if (!Format::operator==(rhs) ||
502        fPattern != that.fPattern ||
503        fLocale != that.fLocale ||
504        isArgNumeric != that.isArgNumeric) {
505        return FALSE;
506    }
507
508    int32_t j;
509    for (j=0; j<subformatCount; ++j) {
510        if (subformats[j] != that.subformats[j]) {
511            return FALSE;
512        }
513    }
514
515    return TRUE;
516}
517
518// -------------------------------------
519// Creates a copy of this MessageFormat, the caller owns the copy.
520
521Format*
522MessageFormat::clone() const
523{
524    return new MessageFormat(*this);
525}
526
527// -------------------------------------
528// Sets the locale of this MessageFormat object to theLocale.
529
530void
531MessageFormat::setLocale(const Locale& theLocale)
532{
533    if (fLocale != theLocale) {
534        delete defaultNumberFormat;
535        defaultNumberFormat = NULL;
536        delete defaultDateFormat;
537        defaultDateFormat = NULL;
538    }
539    fLocale = theLocale;
540    setLocaleIDs(fLocale.getName(), fLocale.getName());
541}
542
543// -------------------------------------
544// Gets the locale of this MessageFormat object.
545
546const Locale&
547MessageFormat::getLocale() const
548{
549    return fLocale;
550}
551
552
553
554
555void
556MessageFormat::applyPattern(const UnicodeString& newPattern,
557                            UErrorCode& status)
558{
559    UParseError parseError;
560    applyPattern(newPattern,parseError,status);
561}
562
563
564// -------------------------------------
565// Applies the new pattern and returns an error if the pattern
566// is not correct.
567void
568MessageFormat::applyPattern(const UnicodeString& pattern,
569                            UParseError& parseError,
570                            UErrorCode& ec)
571{
572    if(U_FAILURE(ec)) {
573        return;
574    }
575    // The pattern is broken up into segments.  Each time a subformat
576    // is encountered, 4 segments are recorded.  For example, consider
577    // the pattern:
578    //  "There {0,choice,0.0#are no files|1.0#is one file|1.0<are {0, number} files} on disk {1}."
579    // The first set of segments is:
580    //  segments[0] = "There "
581    //  segments[1] = "0"
582    //  segments[2] = "choice"
583    //  segments[3] = "0.0#are no files|1.0#is one file|1.0<are {0, number} files"
584
585    // During parsing, the plain text is accumulated into segments[0].
586    // Segments 1..3 are used to parse each subpattern.  Each time a
587    // subpattern is parsed, it creates a format object that is stored
588    // in the subformats array, together with an offset and argument
589    // number.  The offset into the plain text stored in
590    // segments[0].
591
592    // Quotes in segment 0 are handled normally.  They are removed.
593    // Quotes may not occur in segments 1 or 2.
594    // Quotes in segment 3 are parsed and _copied_.  This makes
595    //  subformat patterns work, e.g., {1,number,'#'.##} passes
596    //  the pattern "'#'.##" to DecimalFormat.
597
598    UnicodeString segments[4];
599    int32_t part = 0; // segment we are in, 0..3
600    // Record the highest argument number in the pattern.  (In the
601    // subpattern {3,number} the argument number is 3.)
602    int32_t formatNumber = 0;
603    UBool inQuote = FALSE;
604    int32_t braceStack = 0;
605    // Clear error struct
606    parseError.offset = -1;
607    parseError.preContext[0] = parseError.postContext[0] = (UChar)0;
608    int32_t patLen = pattern.length();
609    int32_t i;
610
611    for (i=0; i<subformatCount; ++i) {
612        delete subformats[i].format;
613    }
614    subformatCount = 0;
615    argTypeCount = 0;
616
617    for (i=0; i<patLen; ++i) {
618        UChar ch = pattern[i];
619        if (part == 0) {
620            // In segment 0, recognize and remove quotes
621            if (ch == SINGLE_QUOTE) {
622                if (i+1 < patLen && pattern[i+1] == SINGLE_QUOTE) {
623                    segments[0] += ch;
624                    ++i;
625                } else {
626                    inQuote = !inQuote;
627                }
628            } else if (ch == LEFT_CURLY_BRACE && !inQuote) {
629                // The only way we get from segment 0 to 1 is via an
630                // unquoted '{'.
631                part = 1;
632            } else {
633                segments[0] += ch;
634            }
635        } else if (inQuote) {
636            // In segments 1..3, recognize quoted matter, and copy it
637            // into the segment, together with the quotes.  This takes
638            // care of '' as well.
639            segments[part] += ch;
640            if (ch == SINGLE_QUOTE) {
641                inQuote = FALSE;
642            }
643        } else {
644            // We have an unquoted character in segment 1..3
645            switch (ch) {
646            case COMMA:
647                // Commas bump us to the next segment, except for segment 3,
648                // which can contain commas.  See example above.
649                if (part < 3)
650                    part += 1;
651                else
652                    segments[3] += ch;
653                break;
654            case LEFT_CURLY_BRACE:
655                // Handle '{' within segment 3.  The initial '{'
656                // before segment 1 is handled above.
657                if (part != 3) {
658                    ec = U_PATTERN_SYNTAX_ERROR;
659                    goto SYNTAX_ERROR;
660                }
661                ++braceStack;
662                segments[part] += ch;
663                break;
664            case RIGHT_CURLY_BRACE:
665                if (braceStack == 0) {
666                    makeFormat(formatNumber, segments, parseError,ec);
667                    if (U_FAILURE(ec)){
668                        goto SYNTAX_ERROR;
669                    }
670                    formatNumber++;
671
672                    segments[1].remove();
673                    segments[2].remove();
674                    segments[3].remove();
675                    part = 0;
676                } else {
677                    --braceStack;
678                    segments[part] += ch;
679                }
680                break;
681            case SINGLE_QUOTE:
682                inQuote = TRUE;
683                // fall through (copy quote chars in segments 1..3)
684            default:
685                segments[part] += ch;
686                break;
687            }
688        }
689    }
690    if (braceStack != 0 || part != 0) {
691        // Unmatched braces in the pattern
692        ec = U_UNMATCHED_BRACES;
693        goto SYNTAX_ERROR;
694    }
695    fPattern = segments[0];
696    return;
697
698 SYNTAX_ERROR:
699    syntaxError(pattern, i, parseError);
700    for (i=0; i<subformatCount; ++i) {
701        delete subformats[i].format;
702    }
703    argTypeCount = subformatCount = 0;
704}
705// -------------------------------------
706// Converts this MessageFormat instance to a pattern.
707
708UnicodeString&
709MessageFormat::toPattern(UnicodeString& appendTo) const {
710    // later, make this more extensible
711    int32_t lastOffset = 0;
712    int32_t i;
713    for (i=0; i<subformatCount; ++i) {
714        copyAndFixQuotes(fPattern, lastOffset, subformats[i].offset, appendTo);
715        lastOffset = subformats[i].offset;
716        appendTo += LEFT_CURLY_BRACE;
717        if (isArgNumeric) {
718            itos(subformats[i].argNum, appendTo);
719        }
720        else {
721            appendTo += *subformats[i].argName;
722        }
723        Format* fmt = subformats[i].format;
724        DecimalFormat* decfmt;
725        SimpleDateFormat* sdtfmt;
726        ChoiceFormat* chcfmt;
727        PluralFormat* plfmt;
728        SelectFormat* selfmt;
729        if (fmt == NULL) {
730            // do nothing, string format
731        }
732        else if ((decfmt = dynamic_cast<DecimalFormat*>(fmt)) != NULL) {
733            UErrorCode ec = U_ZERO_ERROR;
734            NumberFormat& formatAlias = *decfmt;
735            NumberFormat *defaultTemplate = NumberFormat::createInstance(fLocale, ec);
736            NumberFormat *currencyTemplate = NumberFormat::createCurrencyInstance(fLocale, ec);
737            NumberFormat *percentTemplate = NumberFormat::createPercentInstance(fLocale, ec);
738            NumberFormat *integerTemplate = createIntegerFormat(fLocale, ec);
739
740            appendTo += COMMA;
741            appendTo += ID_NUMBER;
742            if (formatAlias != *defaultTemplate) {
743                appendTo += COMMA;
744                if (formatAlias == *currencyTemplate) {
745                    appendTo += ID_CURRENCY;
746                }
747                else if (formatAlias == *percentTemplate) {
748                    appendTo += ID_PERCENT;
749                }
750                else if (formatAlias == *integerTemplate) {
751                    appendTo += ID_INTEGER;
752                }
753                else {
754                    UnicodeString buffer;
755                    appendTo += decfmt->toPattern(buffer);
756                }
757            }
758
759            delete defaultTemplate;
760            delete currencyTemplate;
761            delete percentTemplate;
762            delete integerTemplate;
763        }
764        else if ((sdtfmt = dynamic_cast<SimpleDateFormat*>(fmt)) != NULL) {
765            DateFormat& formatAlias = *sdtfmt;
766            DateFormat *defaultDateTemplate = DateFormat::createDateInstance(DateFormat::kDefault, fLocale);
767            DateFormat *shortDateTemplate = DateFormat::createDateInstance(DateFormat::kShort, fLocale);
768            DateFormat *longDateTemplate = DateFormat::createDateInstance(DateFormat::kLong, fLocale);
769            DateFormat *fullDateTemplate = DateFormat::createDateInstance(DateFormat::kFull, fLocale);
770            DateFormat *defaultTimeTemplate = DateFormat::createTimeInstance(DateFormat::kDefault, fLocale);
771            DateFormat *shortTimeTemplate = DateFormat::createTimeInstance(DateFormat::kShort, fLocale);
772            DateFormat *longTimeTemplate = DateFormat::createTimeInstance(DateFormat::kLong, fLocale);
773            DateFormat *fullTimeTemplate = DateFormat::createTimeInstance(DateFormat::kFull, fLocale);
774
775
776            appendTo += COMMA;
777            if (formatAlias == *defaultDateTemplate) {
778                // default is medium. no need to handle medium separately.
779                appendTo += ID_DATE;
780            }
781            else if (formatAlias == *shortDateTemplate) {
782                appendTo += ID_DATE;
783                appendTo += COMMA;
784                appendTo += ID_SHORT;
785            }
786            else if (formatAlias == *longDateTemplate) {
787                appendTo += ID_DATE;
788                appendTo += COMMA;
789                appendTo += ID_LONG;
790            }
791            else if (formatAlias == *fullDateTemplate) {
792                appendTo += ID_DATE;
793                appendTo += COMMA;
794                appendTo += ID_FULL;
795            }
796            else if (formatAlias == *defaultTimeTemplate) {
797                // default is medium. no need to handle medium separately.
798                appendTo += ID_TIME;
799            }
800            else if (formatAlias == *shortTimeTemplate) {
801                appendTo += ID_TIME;
802                appendTo += COMMA;
803                appendTo += ID_SHORT;
804            }
805            else if (formatAlias == *longTimeTemplate) {
806                appendTo += ID_TIME;
807                appendTo += COMMA;
808                appendTo += ID_LONG;
809            }
810            else if (formatAlias == *fullTimeTemplate) {
811                appendTo += ID_TIME;
812                appendTo += COMMA;
813                appendTo += ID_FULL;
814            }
815            else {
816                UnicodeString buffer;
817                appendTo += ID_DATE;
818                appendTo += COMMA;
819                appendTo += sdtfmt->toPattern(buffer);
820            }
821
822            delete defaultDateTemplate;
823            delete shortDateTemplate;
824            delete longDateTemplate;
825            delete fullDateTemplate;
826            delete defaultTimeTemplate;
827            delete shortTimeTemplate;
828            delete longTimeTemplate;
829            delete fullTimeTemplate;
830            // {sfb} there should be a more efficient way to do this!
831        }
832        else if ((chcfmt = dynamic_cast<ChoiceFormat*>(fmt)) != NULL) {
833            UnicodeString buffer;
834            appendTo += COMMA;
835            appendTo += ID_CHOICE;
836            appendTo += COMMA;
837            appendTo += ((ChoiceFormat*)fmt)->toPattern(buffer);
838        }
839        else if ((plfmt = dynamic_cast<PluralFormat*>(fmt)) != NULL) {
840            UnicodeString buffer;
841            appendTo += plfmt->toPattern(buffer);
842        }
843        else if ((selfmt = dynamic_cast<SelectFormat*>(fmt)) != NULL) {
844            UnicodeString buffer;
845            appendTo += ((SelectFormat*)fmt)->toPattern(buffer);
846        }
847        else {
848            //appendTo += ", unknown";
849        }
850        appendTo += RIGHT_CURLY_BRACE;
851    }
852    copyAndFixQuotes(fPattern, lastOffset, fPattern.length(), appendTo);
853    return appendTo;
854}
855
856// -------------------------------------
857// Adopts the new formats array and updates the array count.
858// This MessageFormat instance owns the new formats.
859
860void
861MessageFormat::adoptFormats(Format** newFormats,
862                            int32_t count) {
863    if (newFormats == NULL || count < 0) {
864        return;
865    }
866
867    int32_t i;
868    if (allocateSubformats(count)) {
869        for (i=0; i<subformatCount; ++i) {
870            delete subformats[i].format;
871        }
872        for (i=0; i<count; ++i) {
873            subformats[i].format = newFormats[i];
874        }
875        subformatCount = count;
876    } else {
877        // An adopt method must always take ownership.  Delete
878        // the incoming format objects and return unchanged.
879        for (i=0; i<count; ++i) {
880            delete newFormats[i];
881        }
882    }
883
884    // TODO: What about the .offset and .argNum fields?
885}
886
887// -------------------------------------
888// Sets the new formats array and updates the array count.
889// This MessageFormat instance maks a copy of the new formats.
890
891void
892MessageFormat::setFormats(const Format** newFormats,
893                          int32_t count) {
894    if (newFormats == NULL || count < 0) {
895        return;
896    }
897
898    if (allocateSubformats(count)) {
899        int32_t i;
900        for (i=0; i<subformatCount; ++i) {
901            delete subformats[i].format;
902        }
903        subformatCount = 0;
904
905        for (i=0; i<count; ++i) {
906            subformats[i].format = newFormats[i] ? newFormats[i]->clone() : NULL;
907        }
908        subformatCount = count;
909    }
910
911    // TODO: What about the .offset and .arg fields?
912}
913
914// -------------------------------------
915// Adopt a single format by format number.
916// Do nothing if the format number is not less than the array count.
917
918void
919MessageFormat::adoptFormat(int32_t n, Format *newFormat) {
920    if (n < 0 || n >= subformatCount) {
921        delete newFormat;
922    } else {
923        delete subformats[n].format;
924        subformats[n].format = newFormat;
925    }
926}
927
928// -------------------------------------
929// Adopt a single format by format name.
930// Do nothing if there is no match of formatName.
931void
932MessageFormat::adoptFormat(const UnicodeString& formatName,
933                           Format* formatToAdopt,
934                           UErrorCode& status) {
935    if (isArgNumeric ) {
936        int32_t argumentNumber = stou(formatName);
937        if (argumentNumber<0) {
938            status = U_ARGUMENT_TYPE_MISMATCH;
939            return;
940        }
941        adoptFormat(argumentNumber, formatToAdopt);
942        return;
943    }
944    for (int32_t i=0; i<subformatCount; ++i) {
945        if (formatName==*subformats[i].argName) {
946            delete subformats[i].format;
947            if ( formatToAdopt== NULL) {
948                // This should never happen -- but we'll be nice if it does
949                subformats[i].format = NULL;
950            } else {
951                subformats[i].format = formatToAdopt;
952            }
953        }
954    }
955}
956
957// -------------------------------------
958// Set a single format.
959// Do nothing if the variable is not less than the array count.
960
961void
962MessageFormat::setFormat(int32_t n, const Format& newFormat) {
963    if (n >= 0 && n < subformatCount) {
964        delete subformats[n].format;
965        if (&newFormat == NULL) {
966            // This should never happen -- but we'll be nice if it does
967            subformats[n].format = NULL;
968        } else {
969            subformats[n].format = newFormat.clone();
970        }
971    }
972}
973
974// -------------------------------------
975// Get a single format by format name.
976// Do nothing if the variable is not less than the array count.
977Format *
978MessageFormat::getFormat(const UnicodeString& formatName, UErrorCode& status) {
979
980    if (U_FAILURE(status)) return NULL;
981
982    if (isArgNumeric ) {
983        int32_t argumentNumber = stou(formatName);
984        if (argumentNumber<0) {
985            status = U_ARGUMENT_TYPE_MISMATCH;
986            return NULL;
987        }
988        if (argumentNumber < 0 || argumentNumber >= subformatCount) {
989            return subformats[argumentNumber].format;
990        }
991        else {
992            return NULL;
993        }
994    }
995
996    for (int32_t i=0; i<subformatCount; ++i) {
997        if (formatName==*subformats[i].argName)
998        {
999            return subformats[i].format;
1000        }
1001    }
1002    return NULL;
1003}
1004
1005// -------------------------------------
1006// Set a single format by format name
1007// Do nothing if the variable is not less than the array count.
1008void
1009MessageFormat::setFormat(const UnicodeString& formatName,
1010                         const Format& newFormat,
1011                         UErrorCode& status) {
1012    if (isArgNumeric) {
1013        status = U_ARGUMENT_TYPE_MISMATCH;
1014        return;
1015    }
1016    for (int32_t i=0; i<subformatCount; ++i) {
1017        if (formatName==*subformats[i].argName)
1018        {
1019            delete subformats[i].format;
1020            if (&newFormat == NULL) {
1021                // This should never happen -- but we'll be nice if it does
1022                subformats[i].format = NULL;
1023            } else {
1024                subformats[i].format = newFormat.clone();
1025            }
1026            break;
1027        }
1028    }
1029}
1030
1031// -------------------------------------
1032// Gets the format array.
1033
1034const Format**
1035MessageFormat::getFormats(int32_t& cnt) const
1036{
1037    // This old API returns an array (which we hold) of Format*
1038    // pointers.  The array is valid up to the next call to any
1039    // method on this object.  We construct and resize an array
1040    // on demand that contains aliases to the subformats[i].format
1041    // pointers.
1042    MessageFormat* t = (MessageFormat*) this;
1043    cnt = 0;
1044    if (formatAliases == NULL) {
1045        t->formatAliasesCapacity = (subformatCount<10) ? 10 : subformatCount;
1046        Format** a = (Format**)
1047            uprv_malloc(sizeof(Format*) * formatAliasesCapacity);
1048        if (a == NULL) {
1049            return NULL;
1050        }
1051        t->formatAliases = a;
1052    } else if (subformatCount > formatAliasesCapacity) {
1053        Format** a = (Format**)
1054            uprv_realloc(formatAliases, sizeof(Format*) * subformatCount);
1055        if (a == NULL) {
1056            return NULL;
1057        }
1058        t->formatAliases = a;
1059        t->formatAliasesCapacity = subformatCount;
1060    }
1061    for (int32_t i=0; i<subformatCount; ++i) {
1062        t->formatAliases[i] = subformats[i].format;
1063    }
1064    cnt = subformatCount;
1065    return (const Format**)formatAliases;
1066}
1067
1068
1069StringEnumeration*
1070MessageFormat::getFormatNames(UErrorCode& status) {
1071    if (U_FAILURE(status))  return NULL;
1072
1073    if (isArgNumeric) {
1074        status = U_ARGUMENT_TYPE_MISMATCH;
1075        return NULL;
1076    }
1077    UVector *fFormatNames = new UVector(status);
1078    if (U_FAILURE(status)) {
1079        status = U_MEMORY_ALLOCATION_ERROR;
1080        return NULL;
1081    }
1082    for (int32_t i=0; i<subformatCount; ++i) {
1083        fFormatNames->addElement(new UnicodeString(*subformats[i].argName), status);
1084    }
1085
1086    StringEnumeration* nameEnumerator = new FormatNameEnumeration(fFormatNames, status);
1087    return nameEnumerator;
1088}
1089
1090// -------------------------------------
1091// Formats the source Formattable array and copy into the result buffer.
1092// Ignore the FieldPosition result for error checking.
1093
1094UnicodeString&
1095MessageFormat::format(const Formattable* source,
1096                      int32_t cnt,
1097                      UnicodeString& appendTo,
1098                      FieldPosition& ignore,
1099                      UErrorCode& success) const
1100{
1101    if (U_FAILURE(success))
1102        return appendTo;
1103
1104    return format(source, cnt, appendTo, ignore, 0, success);
1105}
1106
1107// -------------------------------------
1108// Internally creates a MessageFormat instance based on the
1109// pattern and formats the arguments Formattable array and
1110// copy into the appendTo buffer.
1111
1112UnicodeString&
1113MessageFormat::format(  const UnicodeString& pattern,
1114                        const Formattable* arguments,
1115                        int32_t cnt,
1116                        UnicodeString& appendTo,
1117                        UErrorCode& success)
1118{
1119    MessageFormat temp(pattern, success);
1120    FieldPosition ignore(0);
1121    temp.format(arguments, cnt, appendTo, ignore, success);
1122    return appendTo;
1123}
1124
1125// -------------------------------------
1126// Formats the source Formattable object and copy into the
1127// appendTo buffer.  The Formattable object must be an array
1128// of Formattable instances, returns error otherwise.
1129
1130UnicodeString&
1131MessageFormat::format(const Formattable& source,
1132                      UnicodeString& appendTo,
1133                      FieldPosition& ignore,
1134                      UErrorCode& success) const
1135{
1136    int32_t cnt;
1137
1138    if (U_FAILURE(success))
1139        return appendTo;
1140    if (source.getType() != Formattable::kArray) {
1141        success = U_ILLEGAL_ARGUMENT_ERROR;
1142        return appendTo;
1143    }
1144    const Formattable* tmpPtr = source.getArray(cnt);
1145
1146    return format(tmpPtr, cnt, appendTo, ignore, 0, success);
1147}
1148
1149
1150UnicodeString&
1151MessageFormat::format(const UnicodeString* argumentNames,
1152                      const Formattable* arguments,
1153                      int32_t count,
1154                      UnicodeString& appendTo,
1155                      UErrorCode& success) const {
1156    FieldPosition ignore(0);
1157    return format(arguments, argumentNames, count, appendTo, ignore, 0, success);
1158}
1159
1160UnicodeString&
1161MessageFormat::format(const Formattable* arguments,
1162                      int32_t cnt,
1163                      UnicodeString& appendTo,
1164                      FieldPosition& status,
1165                      int32_t recursionProtection,
1166                      UErrorCode& success) const
1167{
1168    return format(arguments, NULL, cnt, appendTo, status, recursionProtection, success);
1169}
1170
1171// -------------------------------------
1172// Formats the arguments Formattable array and copy into the appendTo buffer.
1173// Ignore the FieldPosition result for error checking.
1174
1175UnicodeString&
1176MessageFormat::format(const Formattable* arguments,
1177                      const UnicodeString *argumentNames,
1178                      int32_t cnt,
1179                      UnicodeString& appendTo,
1180                      FieldPosition& status,
1181                      int32_t recursionProtection,
1182                      UErrorCode& success) const
1183{
1184    int32_t lastOffset = 0;
1185    int32_t argumentNumber=0;
1186    if (cnt < 0 || (cnt && arguments == NULL)) {
1187        success = U_ILLEGAL_ARGUMENT_ERROR;
1188        return appendTo;
1189    }
1190
1191    if ( !isArgNumeric && argumentNames== NULL ) {
1192        success = U_ILLEGAL_ARGUMENT_ERROR;
1193        return appendTo;
1194    }
1195
1196    const Formattable *obj=NULL;
1197    for (int32_t i=0; i<subformatCount; ++i) {
1198        // Append the prefix of current format element.
1199        appendTo.append(fPattern, lastOffset, subformats[i].offset - lastOffset);
1200        lastOffset = subformats[i].offset;
1201        obj = NULL;
1202        if (isArgNumeric) {
1203            argumentNumber = subformats[i].argNum;
1204
1205            // Checks the scope of the argument number.
1206            if (argumentNumber >= cnt) {
1207                appendTo += LEFT_CURLY_BRACE;
1208                itos(argumentNumber, appendTo);
1209                appendTo += RIGHT_CURLY_BRACE;
1210                continue;
1211            }
1212            obj = arguments+argumentNumber;
1213        }
1214        else {
1215            for (int32_t j=0; j<cnt; ++j) {
1216                if (argumentNames[j]== *subformats[i].argName ) {
1217                    obj = arguments+j;
1218                    break;
1219                }
1220            }
1221            if (obj == NULL ) {
1222                appendTo += LEFT_CURLY_BRACE;
1223                appendTo += *subformats[i].argName;
1224                appendTo += RIGHT_CURLY_BRACE;
1225                continue;
1226
1227            }
1228        }
1229        Formattable::Type type = obj->getType();
1230
1231        // Recursively calling the format process only if the current
1232        // format argument refers to either of the following:
1233        // a ChoiceFormat object, a PluralFormat object, a SelectFormat object.
1234        Format* fmt = subformats[i].format;
1235        if (fmt != NULL) {
1236            UnicodeString argNum;
1237            fmt->format(*obj, argNum, success);
1238
1239            // Needs to reprocess the ChoiceFormat and PluralFormat and SelectFormat option by using the
1240            // MessageFormat pattern application.
1241            if ((dynamic_cast<ChoiceFormat*>(fmt) != NULL ||
1242                 dynamic_cast<PluralFormat*>(fmt) != NULL ||
1243                 dynamic_cast<SelectFormat*>(fmt) != NULL) &&
1244                argNum.indexOf(LEFT_CURLY_BRACE) >= 0
1245            ) {
1246                MessageFormat temp(argNum, fLocale, success);
1247                // TODO: Implement recursion protection
1248                if ( isArgNumeric ) {
1249                    temp.format(arguments, NULL, cnt, appendTo, status, recursionProtection, success);
1250                }
1251                else {
1252                    temp.format(arguments, argumentNames, cnt, appendTo, status, recursionProtection, success);
1253                }
1254                if (U_FAILURE(success)) {
1255                    return appendTo;
1256                }
1257            }
1258            else {
1259                appendTo += argNum;
1260            }
1261        }
1262        // If the obj data type is a number, use a NumberFormat instance.
1263        else if ((type == Formattable::kDouble) ||
1264                 (type == Formattable::kLong) ||
1265                 (type == Formattable::kInt64)) {
1266
1267            const NumberFormat* nf = getDefaultNumberFormat(success);
1268            if (nf == NULL) {
1269                return appendTo;
1270            }
1271            if (type == Formattable::kDouble) {
1272                nf->format(obj->getDouble(), appendTo);
1273            } else if (type == Formattable::kLong) {
1274                nf->format(obj->getLong(), appendTo);
1275            } else {
1276                nf->format(obj->getInt64(), appendTo);
1277            }
1278        }
1279        // If the obj data type is a Date instance, use a DateFormat instance.
1280        else if (type == Formattable::kDate) {
1281            const DateFormat* df = getDefaultDateFormat(success);
1282            if (df == NULL) {
1283                return appendTo;
1284            }
1285            df->format(obj->getDate(), appendTo);
1286        }
1287        else if (type == Formattable::kString) {
1288            appendTo += obj->getString();
1289        }
1290        else {
1291            success = U_ILLEGAL_ARGUMENT_ERROR;
1292            return appendTo;
1293        }
1294    }
1295    // Appends the rest of the pattern characters after the real last offset.
1296    appendTo.append(fPattern, lastOffset, 0x7fffffff);
1297    return appendTo;
1298}
1299
1300
1301// -------------------------------------
1302// Parses the source pattern and returns the Formattable objects array,
1303// the array count and the ending parse position.  The caller of this method
1304// owns the array.
1305
1306Formattable*
1307MessageFormat::parse(const UnicodeString& source,
1308                     ParsePosition& pos,
1309                     int32_t& count) const
1310{
1311    // Allocate at least one element.  Allocating an array of length
1312    // zero causes problems on some platforms (e.g. Win32).
1313    Formattable *resultArray = new Formattable[argTypeCount ? argTypeCount : 1];
1314    int32_t patternOffset = 0;
1315    int32_t sourceOffset = pos.getIndex();
1316    ParsePosition tempPos(0);
1317    count = 0; // {sfb} reset to zero
1318    int32_t len;
1319    // If resultArray could not be created, exit out.
1320    // Avoid crossing initialization of variables above.
1321    if (resultArray == NULL) {
1322        goto PARSE_ERROR;
1323    }
1324    for (int32_t i = 0; i < subformatCount; ++i) {
1325        // match up to format
1326        len = subformats[i].offset - patternOffset;
1327        if (len == 0 ||
1328            fPattern.compare(patternOffset, len, source, sourceOffset, len) == 0) {
1329            sourceOffset += len;
1330            patternOffset += len;
1331        }
1332        else {
1333            goto PARSE_ERROR;
1334        }
1335
1336        // now use format
1337        Format* fmt = subformats[i].format;
1338        int32_t argNum = subformats[i].argNum;
1339        if (fmt == NULL) {   // string format
1340            // if at end, use longest possible match
1341            // otherwise uses first match to intervening string
1342            // does NOT recursively try all possibilities
1343            int32_t tempLength = (i+1<subformatCount) ?
1344                subformats[i+1].offset : fPattern.length();
1345
1346            int32_t next;
1347            if (patternOffset >= tempLength) {
1348                next = source.length();
1349            }
1350            else {
1351                UnicodeString buffer;
1352                fPattern.extract(patternOffset,tempLength - patternOffset, buffer);
1353                next = source.indexOf(buffer, sourceOffset);
1354            }
1355
1356            if (next < 0) {
1357                goto PARSE_ERROR;
1358            }
1359            else {
1360                UnicodeString buffer;
1361                source.extract(sourceOffset,next - sourceOffset, buffer);
1362                UnicodeString strValue = buffer;
1363                UnicodeString temp(LEFT_CURLY_BRACE);
1364                // {sfb} check this later
1365                if (isArgNumeric) {
1366                    itos(argNum, temp);
1367                }
1368                else {
1369                    temp+=(*subformats[i].argName);
1370                }
1371                temp += RIGHT_CURLY_BRACE;
1372                if (strValue != temp) {
1373                    source.extract(sourceOffset,next - sourceOffset, buffer);
1374                    resultArray[argNum].setString(buffer);
1375                    // {sfb} not sure about this
1376                    if ((argNum + 1) > count) {
1377                        count = argNum + 1;
1378                    }
1379                }
1380                sourceOffset = next;
1381            }
1382        }
1383        else {
1384            tempPos.setIndex(sourceOffset);
1385            fmt->parseObject(source, resultArray[argNum], tempPos);
1386            if (tempPos.getIndex() == sourceOffset) {
1387                goto PARSE_ERROR;
1388            }
1389
1390            if ((argNum + 1) > count) {
1391                count = argNum + 1;
1392            }
1393            sourceOffset = tempPos.getIndex(); // update
1394        }
1395    }
1396    len = fPattern.length() - patternOffset;
1397    if (len == 0 ||
1398        fPattern.compare(patternOffset, len, source, sourceOffset, len) == 0) {
1399        pos.setIndex(sourceOffset + len);
1400        return resultArray;
1401    }
1402    // else fall through...
1403
1404 PARSE_ERROR:
1405    pos.setErrorIndex(sourceOffset);
1406    delete [] resultArray;
1407    count = 0;
1408    return NULL; // leave index as is to signal error
1409}
1410
1411// -------------------------------------
1412// Parses the source string and returns the array of
1413// Formattable objects and the array count.  The caller
1414// owns the returned array.
1415
1416Formattable*
1417MessageFormat::parse(const UnicodeString& source,
1418                     int32_t& cnt,
1419                     UErrorCode& success) const
1420{
1421    if (!isArgNumeric ) {
1422        success = U_ARGUMENT_TYPE_MISMATCH;
1423        return NULL;
1424    }
1425    ParsePosition status(0);
1426    // Calls the actual implementation method and starts
1427    // from zero offset of the source text.
1428    Formattable* result = parse(source, status, cnt);
1429    if (status.getIndex() == 0) {
1430        success = U_MESSAGE_PARSE_ERROR;
1431        delete[] result;
1432        return NULL;
1433    }
1434    return result;
1435}
1436
1437// -------------------------------------
1438// Parses the source text and copy into the result buffer.
1439
1440void
1441MessageFormat::parseObject( const UnicodeString& source,
1442                            Formattable& result,
1443                            ParsePosition& status) const
1444{
1445    int32_t cnt = 0;
1446    Formattable* tmpResult = parse(source, status, cnt);
1447    if (tmpResult != NULL)
1448        result.adoptArray(tmpResult, cnt);
1449}
1450
1451UnicodeString
1452MessageFormat::autoQuoteApostrophe(const UnicodeString& pattern, UErrorCode& status) {
1453  UnicodeString result;
1454  if (U_SUCCESS(status)) {
1455    int32_t plen = pattern.length();
1456    const UChar* pat = pattern.getBuffer();
1457    int32_t blen = plen * 2 + 1; // space for null termination, convenience
1458    UChar* buf = result.getBuffer(blen);
1459    if (buf == NULL) {
1460      status = U_MEMORY_ALLOCATION_ERROR;
1461    } else {
1462      int32_t len = umsg_autoQuoteApostrophe(pat, plen, buf, blen, &status);
1463      result.releaseBuffer(U_SUCCESS(status) ? len : 0);
1464    }
1465  }
1466  if (U_FAILURE(status)) {
1467    result.setToBogus();
1468  }
1469  return result;
1470}
1471
1472// -------------------------------------
1473
1474static Format* makeRBNF(URBNFRuleSetTag tag, const Locale& locale, const UnicodeString& defaultRuleSet, UErrorCode& ec) {
1475    RuleBasedNumberFormat* fmt = new RuleBasedNumberFormat(tag, locale, ec);
1476    if (fmt == NULL) {
1477        ec = U_MEMORY_ALLOCATION_ERROR;
1478    } else if (U_SUCCESS(ec) && defaultRuleSet.length() > 0) {
1479        UErrorCode localStatus = U_ZERO_ERROR; // ignore unrecognized default rule set
1480        fmt->setDefaultRuleSet(defaultRuleSet, localStatus);
1481    }
1482    return fmt;
1483}
1484
1485/**
1486 * Reads the segments[] array (see applyPattern()) and parses the
1487 * segments[1..3] into a Format* object.  Stores the format object in
1488 * the subformats[] array.  Updates the argTypes[] array type
1489 * information for the corresponding argument.
1490 *
1491 * @param formatNumber index into subformats[] for this format
1492 * @param segments array of strings with the parsed pattern segments
1493 * @param parseError parse error data (output param)
1494 * @param ec error code
1495 */
1496void
1497MessageFormat::makeFormat(int32_t formatNumber,
1498                          UnicodeString* segments,
1499                          UParseError& parseError,
1500                          UErrorCode& ec) {
1501    if (U_FAILURE(ec)) {
1502        return;
1503    }
1504
1505    // Parse the argument number
1506    int32_t argumentNumber = stou(segments[1]); // always unlocalized!
1507    UnicodeString argumentName;
1508    if (argumentNumber < 0) {
1509        if ( (isArgNumeric==TRUE) && (formatNumber !=0) ) {
1510            ec = U_INVALID_FORMAT_ERROR;
1511            return;
1512        }
1513        isArgNumeric = FALSE;
1514        argumentNumber=formatNumber;
1515    }
1516    if (!isArgNumeric) {
1517        if ( !isLegalArgName(segments[1]) ) {
1518            ec = U_INVALID_FORMAT_ERROR;
1519            return;
1520        }
1521        argumentName = segments[1];
1522    }
1523
1524    // Parse the format, recording the argument type and creating a
1525    // new Format object (except for string arguments).
1526    Formattable::Type argType;
1527    Format *fmt = NULL;
1528    int32_t typeID, styleID;
1529    DateFormat::EStyle style;
1530    UnicodeString unquotedPattern, quotedPattern;
1531    UBool inQuote = FALSE;
1532
1533    switch (typeID = findKeyword(segments[2], TYPE_IDS)) {
1534
1535    case 0: // string
1536        argType = Formattable::kString;
1537        break;
1538
1539    case 1: // number
1540        argType = Formattable::kDouble;
1541
1542        switch (findKeyword(segments[3], NUMBER_STYLE_IDS)) {
1543        case 0: // default
1544            fmt = NumberFormat::createInstance(fLocale, ec);
1545            break;
1546        case 1: // currency
1547            fmt = NumberFormat::createCurrencyInstance(fLocale, ec);
1548            break;
1549        case 2: // percent
1550            fmt = NumberFormat::createPercentInstance(fLocale, ec);
1551            break;
1552        case 3: // integer
1553            argType = Formattable::kLong;
1554            fmt = createIntegerFormat(fLocale, ec);
1555            break;
1556        default: // pattern
1557            fmt = NumberFormat::createInstance(fLocale, ec);
1558            if (fmt) {
1559                DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fmt);
1560                if (decfmt != NULL) {
1561                    decfmt->applyPattern(segments[3],parseError,ec);
1562                }
1563            }
1564            break;
1565        }
1566        break;
1567
1568    case 2: // date
1569    case 3: // time
1570        argType = Formattable::kDate;
1571        styleID = findKeyword(segments[3], DATE_STYLE_IDS);
1572        style = (styleID >= 0) ? DATE_STYLES[styleID] : DateFormat::kDefault;
1573
1574        if (typeID == 2) {
1575            fmt = DateFormat::createDateInstance(style, fLocale);
1576        } else {
1577            fmt = DateFormat::createTimeInstance(style, fLocale);
1578        }
1579
1580        if (styleID < 0 && fmt != NULL) {
1581            SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(fmt);
1582            if (sdtfmt != NULL) {
1583                sdtfmt->applyPattern(segments[3]);
1584            }
1585        }
1586        break;
1587
1588    case 4: // choice
1589        argType = Formattable::kDouble;
1590
1591        fmt = new ChoiceFormat(segments[3], parseError, ec);
1592        break;
1593
1594    case 5: // spellout
1595        argType = Formattable::kDouble;
1596        fmt = makeRBNF(URBNF_SPELLOUT, fLocale, segments[3], ec);
1597        break;
1598    case 6: // ordinal
1599        argType = Formattable::kDouble;
1600        fmt = makeRBNF(URBNF_ORDINAL, fLocale, segments[3], ec);
1601        break;
1602    case 7: // duration
1603        argType = Formattable::kDouble;
1604        fmt = makeRBNF(URBNF_DURATION, fLocale, segments[3], ec);
1605        break;
1606    case 8: // plural
1607    case 9: // Select
1608        if(typeID == 8)
1609            argType = Formattable::kDouble;
1610        else
1611            argType = Formattable::kString;
1612        quotedPattern = segments[3];
1613        for (int32_t i = 0; i < quotedPattern.length(); ++i) {
1614            UChar ch = quotedPattern.charAt(i);
1615            if (ch == SINGLE_QUOTE) {
1616                if (i+1 < quotedPattern.length() && quotedPattern.charAt(i+1)==SINGLE_QUOTE) {
1617                    unquotedPattern+=ch;
1618                    ++i;
1619                }
1620                else {
1621                    inQuote = !inQuote;
1622                }
1623            }
1624            else {
1625                unquotedPattern += ch;
1626            }
1627        }
1628        if(typeID == 8)
1629            fmt = new PluralFormat(fLocale, unquotedPattern, ec);
1630        else
1631            fmt = new SelectFormat(unquotedPattern, ec);
1632        break;
1633    default:
1634        argType = Formattable::kString;
1635        ec = U_ILLEGAL_ARGUMENT_ERROR;
1636        break;
1637    }
1638
1639    if (fmt==NULL && argType!=Formattable::kString && U_SUCCESS(ec)) {
1640        ec = U_MEMORY_ALLOCATION_ERROR;
1641    }
1642
1643    if (!allocateSubformats(formatNumber+1) ||
1644        !allocateArgTypes(argumentNumber+1)) {
1645        ec = U_MEMORY_ALLOCATION_ERROR;
1646    }
1647
1648    if (U_FAILURE(ec)) {
1649        delete fmt;
1650        return;
1651    }
1652
1653    // Parse succeeded; record results in our arrays
1654    subformats[formatNumber].format = fmt;
1655    subformats[formatNumber].offset = segments[0].length();
1656    if (isArgNumeric) {
1657        subformats[formatNumber].argName = NULL;
1658        subformats[formatNumber].argNum = argumentNumber;
1659    }
1660    else {
1661        subformats[formatNumber].argName = new UnicodeString(argumentName);
1662        subformats[formatNumber].argNum = -1;
1663    }
1664    subformatCount = formatNumber+1;
1665
1666    // Careful here: argumentNumber may in general arrive out of
1667    // sequence, e.g., "There was {2} on {0,date} (see {1,number})."
1668    argTypes[argumentNumber] = argType;
1669    if (argumentNumber+1 > argTypeCount) {
1670        argTypeCount = argumentNumber+1;
1671    }
1672}
1673
1674// -------------------------------------
1675// Finds the string, s, in the string array, list.
1676int32_t MessageFormat::findKeyword(const UnicodeString& s,
1677                                   const UChar * const *list)
1678{
1679    if (s.length() == 0)
1680        return 0; // default
1681
1682    UnicodeString buffer = s;
1683    // Trims the space characters and turns all characters
1684    // in s to lower case.
1685    buffer.trim().toLower("");
1686    for (int32_t i = 0; list[i]; ++i) {
1687        if (!buffer.compare(list[i], u_strlen(list[i]))) {
1688            return i;
1689        }
1690    }
1691    return -1;
1692}
1693
1694// -------------------------------------
1695// Checks the range of the source text to quote the special
1696// characters, { and ' and copy to target buffer.
1697
1698void
1699MessageFormat::copyAndFixQuotes(const UnicodeString& source,
1700                                int32_t start,
1701                                int32_t end,
1702                                UnicodeString& appendTo)
1703{
1704    UBool gotLB = FALSE;
1705
1706    for (int32_t i = start; i < end; ++i) {
1707        UChar ch = source[i];
1708        if (ch == LEFT_CURLY_BRACE) {
1709            appendTo += SINGLE_QUOTE;
1710            appendTo += LEFT_CURLY_BRACE;
1711            appendTo += SINGLE_QUOTE;
1712            gotLB = TRUE;
1713        }
1714        else if (ch == RIGHT_CURLY_BRACE) {
1715            if(gotLB) {
1716                appendTo += RIGHT_CURLY_BRACE;
1717                gotLB = FALSE;
1718            }
1719            else {
1720                // orig code.
1721                appendTo += SINGLE_QUOTE;
1722                appendTo += RIGHT_CURLY_BRACE;
1723                appendTo += SINGLE_QUOTE;
1724            }
1725        }
1726        else if (ch == SINGLE_QUOTE) {
1727            appendTo += SINGLE_QUOTE;
1728            appendTo += SINGLE_QUOTE;
1729        }
1730        else {
1731            appendTo += ch;
1732        }
1733    }
1734}
1735
1736/**
1737 * Convenience method that ought to be in NumberFormat
1738 */
1739NumberFormat*
1740MessageFormat::createIntegerFormat(const Locale& locale, UErrorCode& status) const {
1741    NumberFormat *temp = NumberFormat::createInstance(locale, status);
1742    DecimalFormat *temp2;
1743    if (temp != NULL && (temp2 = dynamic_cast<DecimalFormat*>(temp)) != NULL) {
1744        temp2->setMaximumFractionDigits(0);
1745        temp2->setDecimalSeparatorAlwaysShown(FALSE);
1746        temp2->setParseIntegerOnly(TRUE);
1747    }
1748
1749    return temp;
1750}
1751
1752/**
1753 * Return the default number format.  Used to format a numeric
1754 * argument when subformats[i].format is NULL.  Returns NULL
1755 * on failure.
1756 *
1757 * Semantically const but may modify *this.
1758 */
1759const NumberFormat* MessageFormat::getDefaultNumberFormat(UErrorCode& ec) const {
1760    if (defaultNumberFormat == NULL) {
1761        MessageFormat* t = (MessageFormat*) this;
1762        t->defaultNumberFormat = NumberFormat::createInstance(fLocale, ec);
1763        if (U_FAILURE(ec)) {
1764            delete t->defaultNumberFormat;
1765            t->defaultNumberFormat = NULL;
1766        } else if (t->defaultNumberFormat == NULL) {
1767            ec = U_MEMORY_ALLOCATION_ERROR;
1768        }
1769    }
1770    return defaultNumberFormat;
1771}
1772
1773/**
1774 * Return the default date format.  Used to format a date
1775 * argument when subformats[i].format is NULL.  Returns NULL
1776 * on failure.
1777 *
1778 * Semantically const but may modify *this.
1779 */
1780const DateFormat* MessageFormat::getDefaultDateFormat(UErrorCode& ec) const {
1781    if (defaultDateFormat == NULL) {
1782        MessageFormat* t = (MessageFormat*) this;
1783        t->defaultDateFormat = DateFormat::createDateTimeInstance(DateFormat::kShort, DateFormat::kShort, fLocale);
1784        if (t->defaultDateFormat == NULL) {
1785            ec = U_MEMORY_ALLOCATION_ERROR;
1786        }
1787    }
1788    return defaultDateFormat;
1789}
1790
1791UBool
1792MessageFormat::usesNamedArguments() const {
1793    return !isArgNumeric;
1794}
1795
1796UBool
1797MessageFormat::isLegalArgName(const UnicodeString& argName) const {
1798    if(!u_hasBinaryProperty(argName.charAt(0), idStart)) {
1799        return FALSE;
1800    }
1801    for (int32_t i=1; i<argName.length(); ++i) {
1802        if(!u_hasBinaryProperty(argName.charAt(i), idContinue)) {
1803            return FALSE;
1804        }
1805    }
1806    return TRUE;
1807}
1808
1809int32_t
1810MessageFormat::getArgTypeCount() const {
1811        return argTypeCount;
1812}
1813
1814FormatNameEnumeration::FormatNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) {
1815    pos=0;
1816    fFormatNames = fNameList;
1817}
1818
1819const UnicodeString*
1820FormatNameEnumeration::snext(UErrorCode& status) {
1821    if (U_SUCCESS(status) && pos < fFormatNames->size()) {
1822        return (const UnicodeString*)fFormatNames->elementAt(pos++);
1823    }
1824    return NULL;
1825}
1826
1827void
1828FormatNameEnumeration::reset(UErrorCode& /*status*/) {
1829    pos=0;
1830}
1831
1832int32_t
1833FormatNameEnumeration::count(UErrorCode& /*status*/) const {
1834       return (fFormatNames==NULL) ? 0 : fFormatNames->size();
1835}
1836
1837FormatNameEnumeration::~FormatNameEnumeration() {
1838    UnicodeString *s;
1839    for (int32_t i=0; i<fFormatNames->size(); ++i) {
1840        if ((s=(UnicodeString *)fFormatNames->elementAt(i))!=NULL) {
1841            delete s;
1842        }
1843    }
1844    delete fFormatNames;
1845}
1846U_NAMESPACE_END
1847
1848#endif /* #if !UCONFIG_NO_FORMATTING */
1849
1850//eof
1851