150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho/********************************************************************
227f654740f2a26ad62a5c155af9199af9e69b889claireho * COPYRIGHT:
354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius * Copyright (c) 1997-2012, International Business Machines Corporation and
450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * others. All Rights Reserved.
550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ********************************************************************
650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * File MSGFMT.CPP
850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * Modification History:
1050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *
1150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   Date        Name        Description
1250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   02/19/97    aliu        Converted from java.
1350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   03/20/97    helena      Finished first cut of implementation.
1450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   04/10/97    aliu        Made to work on AIX.  Added stoi to replace wtoi.
1550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   06/11/97    helena      Fixed addPattern to take the pattern correctly.
1650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   06/17/97    helena      Fixed the getPattern to return the correct pattern.
1750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   07/09/97    helena      Made ParsePosition into a class.
1850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *   02/22/99    stephen     Removed character literals for EBCDIC safety
1927f654740f2a26ad62a5c155af9199af9e69b889claireho *   11/01/09    kirtig      Added SelectFormat
2050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ********************************************************************/
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/appendable.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/choicfmt.h"
28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/datefmt.h"
29b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/decimfmt.h"
30b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/localpointer.h"
31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/msgfmt.h"
3285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "unicode/plurfmt.h"
33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/rbnf.h"
3450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "unicode/selfmt.h"
35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/smpdtfmt.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/umsg.h"
37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "unicode/ustring.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h"
40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "messageimpl.h"
4185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "msgfmt_impl.h"
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "uassert.h"
43103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uelement.h"
44103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "uhash.h"
4585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "ustrfmt.h"
46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "util.h"
4785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "uvector.h"
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// class MessageFormat
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// *****************************************************************************
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SINGLE_QUOTE      ((UChar)0x0027)
54b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define COMMA             ((UChar)0x002C)
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define LEFT_CURLY_BRACE  ((UChar)0x007B)
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define RIGHT_CURLY_BRACE ((UChar)0x007D)
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//---------------------------------------
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// static data
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_NUMBER[]    = {
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x6E, 0x75, 0x6D, 0x62, 0x65, 0x72, 0  /* "number" */
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_DATE[]      = {
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x64, 0x61, 0x74, 0x65, 0              /* "date" */
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_TIME[]      = {
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x74, 0x69, 0x6D, 0x65, 0              /* "time" */
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_SPELLOUT[]  = {
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x73, 0x70, 0x65, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0 /* "spellout" */
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_ORDINAL[]   = {
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x6c, 0 /* "ordinal" */
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_DURATION[]  = {
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0 /* "duration" */
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// MessageFormat Type List  Number, Date, Time or Choice
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar * const TYPE_IDS[] = {
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_NUMBER,
8327f654740f2a26ad62a5c155af9199af9e69b889claireho    ID_DATE,
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_TIME,
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_SPELLOUT,
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_ORDINAL,
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_DURATION,
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
9027f654740f2a26ad62a5c155af9199af9e69b889claireho
91b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar ID_EMPTY[]     = {
92b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    0 /* empty string, used for default so that null can mark end of list */
93b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_CURRENCY[]  = {
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x63, 0x75, 0x72, 0x72, 0x65, 0x6E, 0x63, 0x79, 0  /* "currency" */
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_PERCENT[]   = {
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x70, 0x65, 0x72, 0x63, 0x65, 0x6E, 0x74, 0        /* "percent" */
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_INTEGER[]   = {
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x69, 0x6E, 0x74, 0x65, 0x67, 0x65, 0x72, 0        /* "integer" */
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// NumberFormat modifier list, default, currency, percent or integer
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar * const NUMBER_STYLE_IDS[] = {
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_EMPTY,
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_CURRENCY,
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_PERCENT,
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_INTEGER,
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_SHORT[]     = {
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x73, 0x68, 0x6F, 0x72, 0x74, 0        /* "short" */
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_MEDIUM[]    = {
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x6D, 0x65, 0x64, 0x69, 0x75, 0x6D, 0  /* "medium" */
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_LONG[]      = {
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x6C, 0x6F, 0x6E, 0x67, 0              /* "long" */
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar ID_FULL[]      = {
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x66, 0x75, 0x6C, 0x6C, 0              /* "full" */
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// DateFormat modifier list, default, short, medium, long or full
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar * const DATE_STYLE_IDS[] = {
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_EMPTY,
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_SHORT,
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_MEDIUM,
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_LONG,
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ID_FULL,
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NULL,
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
13527f654740f2a26ad62a5c155af9199af9e69b889claireho
136103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic const icu::DateFormat::EStyle DATE_STYLES[] = {
137103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    icu::DateFormat::kDefault,
138103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    icu::DateFormat::kShort,
139103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    icu::DateFormat::kMedium,
140103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    icu::DateFormat::kLong,
141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    icu::DateFormat::kFull,
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const int32_t DEFAULT_INITIAL_CAPACITY = 10;
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar NULL_STRING[] = {
147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    0x6E, 0x75, 0x6C, 0x6C, 0  // "null"
148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar OTHER_STRING[] = {
151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    0x6F, 0x74, 0x68, 0x65, 0x72, 0  // "other"
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho};
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_BEGIN
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool U_CALLCONV equalFormatsForHash(const UHashTok key1,
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            const UHashTok key2) {
157103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return icu::MessageFormat::equalFormats(key1.pointer, key2.pointer);
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoU_CDECL_END
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(MessageFormat)
16685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUOBJECT_DEFINE_RTTI_IMPLEMENTATION(FormatNameEnumeration)
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//--------------------------------------------------------------------
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convert an integer value to a string and append the result to
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * the given UnicodeString.
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UnicodeString& itos(int32_t i, UnicodeString& appendTo) {
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar temp[16];
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_itou(temp,16,i,10,0); // 10 == radix
177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    appendTo.append(temp, -1);
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return appendTo;
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// AppendableWrapper: encapsulates the result of formatting, keeping track
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// of the string and its length.
184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoclass AppendableWrapper : public UMemory {
18585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hopublic:
186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    AppendableWrapper(Appendable& appendable) : app(appendable), len(0) {
18785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void append(const UnicodeString& s) {
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        app.appendString(s.getBuffer(), s.length());
190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len += s.length();
19185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void append(const UChar* s, const int32_t sLength) {
193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        app.appendString(s, sLength);
194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len += sLength;
195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void append(const UnicodeString& s, int32_t start, int32_t length) {
197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        append(s.tempSubString(start, length));
198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void formatAndAppend(const Format* formatter, const Formattable& arg, UErrorCode& ec) {
200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString s;
201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formatter->format(arg, s, ec);
202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(ec)) {
203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            append(s);
204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t length() {
207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return len;
20885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoprivate:
210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    Appendable& app;
211b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t len;
21285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho};
21385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Creates a MessageFormat instance based on the pattern.
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::MessageFormat(const UnicodeString& pattern,
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UErrorCode& success)
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: fLocale(Locale::getDefault()),  // Uses the default locale
221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(success),
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliases(NULL),
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliasesCapacity(0),
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypes(NULL),
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCount(0),
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCapacity(0),
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  hasArgTypeConflicts(FALSE),
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  defaultNumberFormat(NULL),
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  defaultDateFormat(NULL),
230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  cachedFormatters(NULL),
231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  customFormatArgStarts(NULL),
23254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
23354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    setLocaleIDs(fLocale.getName(), fLocale.getName());
236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    applyPattern(pattern, success);
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
23827f654740f2a26ad62a5c155af9199af9e69b889claireho
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::MessageFormat(const UnicodeString& pattern,
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             const Locale& newLocale,
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UErrorCode& success)
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: fLocale(newLocale),
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(success),
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliases(NULL),
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliasesCapacity(0),
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypes(NULL),
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCount(0),
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCapacity(0),
249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  hasArgTypeConflicts(FALSE),
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  defaultNumberFormat(NULL),
251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  defaultDateFormat(NULL),
252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  cachedFormatters(NULL),
253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  customFormatArgStarts(NULL),
25454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
25554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    setLocaleIDs(fLocale.getName(), fLocale.getName());
258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    applyPattern(pattern, success);
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::MessageFormat(const UnicodeString& pattern,
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             const Locale& newLocale,
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UParseError& parseError,
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             UErrorCode& success)
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru: fLocale(newLocale),
266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(success),
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliases(NULL),
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliasesCapacity(0),
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypes(NULL),
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCount(0),
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCapacity(0),
272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  hasArgTypeConflicts(FALSE),
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  defaultNumberFormat(NULL),
274b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  defaultDateFormat(NULL),
275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  cachedFormatters(NULL),
276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  customFormatArgStarts(NULL),
27754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
27854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    setLocaleIDs(fLocale.getName(), fLocale.getName());
281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    applyPattern(pattern, parseError, success);
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::MessageFormat(const MessageFormat& that)
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho:
286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  Format(that),
287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  fLocale(that.fLocale),
288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  msgPattern(that.msgPattern),
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliases(NULL),
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  formatAliasesCapacity(0),
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypes(NULL),
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCount(0),
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  argTypeCapacity(0),
294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  hasArgTypeConflicts(that.hasArgTypeConflicts),
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  defaultNumberFormat(NULL),
296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  defaultDateFormat(NULL),
297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  cachedFormatters(NULL),
298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho  customFormatArgStarts(NULL),
29954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  pluralProvider(&fLocale, UPLURAL_TYPE_CARDINAL),
30054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius  ordinalProvider(&fLocale, UPLURAL_TYPE_ORDINAL)
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // This will take care of creating the hash tables (since they are NULL).
303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    copyObjects(that, ec);
305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        resetPattern();
307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::~MessageFormat()
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(cachedFormatters);
313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(customFormatArgStarts);
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(argTypes);
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(formatAliases);
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete defaultNumberFormat;
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete defaultDateFormat;
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//--------------------------------------------------------------------
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Variable-size array management
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Allocate argTypes[] to at least the given capacity and return
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * TRUE if successful.  If not, leave argTypes[] unchanged.
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * If argTypes is NULL, allocate it.  If it is not NULL, enlarge it
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * if necessary to be at least as large as specified.
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool MessageFormat::allocateArgTypes(int32_t capacity, UErrorCode& status) {
332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (argTypeCapacity >= capacity) {
336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return TRUE;
337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (capacity < DEFAULT_INITIAL_CAPACITY) {
339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        capacity = DEFAULT_INITIAL_CAPACITY;
340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (capacity < 2*argTypeCapacity) {
341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        capacity = 2*argTypeCapacity;
342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    Formattable::Type* a = (Formattable::Type*)
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_realloc(argTypes, sizeof(*argTypes) * capacity);
345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (a == NULL) {
346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_MEMORY_ALLOCATION_ERROR;
347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    argTypes = a;
350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    argTypeCapacity = capacity;
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return TRUE;
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// assignment operator
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst MessageFormat&
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::operator=(const MessageFormat& that)
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (this != &that) {
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // Calls the super class for assignment first.
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Format::operator=(that);
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        setLocale(that.fLocale);
365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgPattern = that.msgPattern;
366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        hasArgTypeConflicts = that.hasArgTypeConflicts;
36727f654740f2a26ad62a5c155af9199af9e69b889claireho
368b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UErrorCode ec = U_ZERO_ERROR;
369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        copyObjects(that, ec);
370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            resetPattern();
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
37827f654740f2a26ad62a5c155af9199af9e69b889clairehoMessageFormat::operator==(const Format& rhs) const
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (this == &rhs) return TRUE;
38127f654740f2a26ad62a5c155af9199af9e69b889claireho
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    MessageFormat& that = (MessageFormat&)rhs;
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Check class ID before checking MessageFormat members
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!Format::operator==(rhs) ||
386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgPattern != that.msgPattern ||
387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLocale != that.fLocale) {
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return FALSE;
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Compare hashtables.
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if ((customFormatArgStarts == NULL) != (that.customFormatArgStarts == NULL)) {
393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (customFormatArgStarts == NULL) {
396b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return TRUE;
397b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
399b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
400b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const int32_t count = uhash_count(customFormatArgStarts);
401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const int32_t rhs_count = uhash_count(that.customFormatArgStarts);
402b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (count != rhs_count) {
403b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return FALSE;
404b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
405b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t idx = 0, rhs_idx = 0, pos = -1, rhs_pos = -1;
406b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (; idx < count && rhs_idx < rhs_count && U_SUCCESS(ec); ++idx, ++rhs_idx) {
407b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UHashElement* cur = uhash_nextElement(customFormatArgStarts, &pos);
408b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UHashElement* rhs_cur = uhash_nextElement(that.customFormatArgStarts, &rhs_pos);
409b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (cur->key.integer != rhs_cur->key.integer) {
410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return FALSE;
411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const Format* format = (const Format*)uhash_iget(cachedFormatters, cur->key.integer);
413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const Format* rhs_format = (const Format*)uhash_iget(that.cachedFormatters, rhs_cur->key.integer);
414b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (*format != *rhs_format) {
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return FALSE;
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return TRUE;
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Creates a copy of this MessageFormat, the caller owns the copy.
42327f654740f2a26ad62a5c155af9199af9e69b889claireho
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat*
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::clone() const
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return new MessageFormat(*this);
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
42927f654740f2a26ad62a5c155af9199af9e69b889claireho
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Sets the locale of this MessageFormat object to theLocale.
43227f654740f2a26ad62a5c155af9199af9e69b889claireho
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::setLocale(const Locale& theLocale)
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (fLocale != theLocale) {
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete defaultNumberFormat;
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        defaultNumberFormat = NULL;
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete defaultDateFormat;
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        defaultDateFormat = NULL;
441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fLocale = theLocale;
442b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setLocaleIDs(fLocale.getName(), fLocale.getName());
443b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        pluralProvider.reset(&fLocale);
44454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        ordinalProvider.reset(&fLocale);
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
44727f654740f2a26ad62a5c155af9199af9e69b889claireho
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Gets the locale of this MessageFormat object.
45027f654740f2a26ad62a5c155af9199af9e69b889claireho
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst Locale&
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::getLocale() const
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fLocale;
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
45827f654740f2a26ad62a5c155af9199af9e69b889clairehoMessageFormat::applyPattern(const UnicodeString& newPattern,
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode& status)
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UParseError parseError;
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    applyPattern(newPattern,parseError,status);
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Applies the new pattern and returns an error if the pattern
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// is not correct.
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
47027f654740f2a26ad62a5c155af9199af9e69b889clairehoMessageFormat::applyPattern(const UnicodeString& pattern,
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UParseError& parseError,
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UErrorCode& ec)
47327f654740f2a26ad62a5c155af9199af9e69b889claireho{
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(U_FAILURE(ec)) {
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msgPattern.parse(pattern, &parseError, ec);
478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cacheExplicitFormats(ec);
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        resetPattern();
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
485b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::resetPattern() {
486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    msgPattern.clear();
487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(cachedFormatters);
488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    cachedFormatters = NULL;
489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_close(customFormatArgStarts);
490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    customFormatArgStarts = NULL;
491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    argTypeCount = 0;
492b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    hasArgTypeConflicts = FALSE;
493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid
496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessageFormat::applyPattern(const UnicodeString& pattern,
497b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            UMessagePatternApostropheMode aposMode,
498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            UParseError* parseError,
499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                            UErrorCode& status) {
500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (aposMode != msgPattern.getApostropheMode()) {
501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgPattern.clearPatternAndSetApostropheMode(aposMode);
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    applyPattern(pattern, *parseError, status);
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
50727f654740f2a26ad62a5c155af9199af9e69b889claireho// Converts this MessageFormat instance to a pattern.
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::toPattern(UnicodeString& appendTo) const {
511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if ((customFormatArgStarts != NULL && 0 != uhash_count(customFormatArgStarts)) ||
512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        0 == msgPattern.countParts()
513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ) {
514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.setToBogus();
515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return appendTo;
516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return appendTo.append(msgPattern.getPatternString());
518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t MessageFormat::nextTopLevelArgStart(int32_t partIndex) const {
521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (partIndex != 0) {
522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        partIndex = msgPattern.getLimitPartIndex(partIndex);
523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (;;) {
525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UMessagePatternPartType type = msgPattern.getPartType(++partIndex);
526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (type == UMSGPAT_PART_TYPE_ARG_START) {
527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return partIndex;
52885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) {
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return -1;
53127f654740f2a26ad62a5c155af9199af9e69b889claireho        }
532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
53427f654740f2a26ad62a5c155af9199af9e69b889claireho
535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::setArgStartFormat(int32_t argStart,
536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                      Format* formatter,
537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                      UErrorCode& status) {
538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete formatter;
540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cachedFormatters == NULL) {
542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        cachedFormatters=uhash_open(uhash_hashLong, uhash_compareLong,
543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    equalFormatsForHash, &status);
544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(status)) {
545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            delete formatter;
546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
54727f654740f2a26ad62a5c155af9199af9e69b889claireho        }
548103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        uhash_setValueDeleter(cachedFormatters, uprv_deleteUObject);
549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (formatter == NULL) {
551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formatter = new DummyFormat();
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_iput(cachedFormatters, argStart, formatter, &status);
554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
55527f654740f2a26ad62a5c155af9199af9e69b889claireho
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool MessageFormat::argNameMatches(int32_t partIndex, const UnicodeString& argName, int32_t argNumber) {
558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const MessagePattern::Part& part = msgPattern.getPart(partIndex);
559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return part.getType() == UMSGPAT_PART_TYPE_ARG_NAME ?
560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        msgPattern.partSubstringMatches(part, argName) :
561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part.getValue() == argNumber;  // ARG_NUMBER
562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Sets a custom formatter for a MessagePattern ARG_START part index.
565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// "Custom" formatters are provided by the user via setFormat() or similar APIs.
566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::setCustomArgStartFormat(int32_t argStart,
567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            Format* formatter,
568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            UErrorCode& status) {
569b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    setArgStartFormat(argStart, formatter, status);
570b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (customFormatArgStarts == NULL) {
571b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        customFormatArgStarts=uhash_open(uhash_hashLong, uhash_compareLong,
572b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                         NULL, &status);
573b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
574b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uhash_iputi(customFormatArgStarts, argStart, 1, &status);
575b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
576b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
577b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoFormat* MessageFormat::getCachedFormatter(int32_t argumentNumber) const {
578b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cachedFormatters == NULL) {
579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
580b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
581b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void* ptr = uhash_iget(cachedFormatters, argumentNumber);
582b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (ptr != NULL && dynamic_cast<DummyFormat*>((Format*)ptr) == NULL) {
583b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return (Format*) ptr;
584b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
585b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Not cached, or a DummyFormat representing setFormat(NULL).
586b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
58927f654740f2a26ad62a5c155af9199af9e69b889claireho
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Adopts the new formats array and updates the array count.
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This MessageFormat instance owns the new formats.
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::adoptFormats(Format** newFormats,
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            int32_t count) {
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (newFormats == NULL || count < 0) {
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
599b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Throw away any cached formatters.
600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cachedFormatters != NULL) {
601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(cachedFormatters);
602b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (customFormatArgStarts != NULL) {
604b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(customFormatArgStarts);
605b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
60627f654740f2a26ad62a5c155af9199af9e69b889claireho
607b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t formatNumber = 0;
608b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t partIndex = 0;
610b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formatNumber < count && U_SUCCESS(status) &&
611b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
612b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        setCustomArgStartFormat(partIndex, newFormats[formatNumber], status);
613b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ++formatNumber;
614b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Delete those that didn't get used (if any).
616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (; formatNumber < count; ++formatNumber) {
617b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        delete newFormats[formatNumber];
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
62027f654740f2a26ad62a5c155af9199af9e69b889claireho}
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Sets the new formats array and updates the array count.
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This MessageFormat instance maks a copy of the new formats.
62527f654740f2a26ad62a5c155af9199af9e69b889claireho
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::setFormats(const Format** newFormats,
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                          int32_t count) {
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (newFormats == NULL || count < 0) {
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Throw away any cached formatters.
633b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cachedFormatters != NULL) {
634b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(cachedFormatters);
635b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (customFormatArgStarts != NULL) {
637b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(customFormatArgStarts);
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
640b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t formatNumber = 0;
642b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t partIndex = 0;
643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formatNumber < count && U_SUCCESS(status) && (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
644b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      Format* newFormat = NULL;
645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if (newFormats[formatNumber] != NULL) {
646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          newFormat = newFormats[formatNumber]->clone();
647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          if (newFormat == NULL) {
648b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho              status = U_MEMORY_ALLOCATION_ERROR;
649b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          }
650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
651b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      setCustomArgStartFormat(partIndex, newFormat, status);
652b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      ++formatNumber;
653b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
654b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
655b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        resetPattern();
656b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
65727f654740f2a26ad62a5c155af9199af9e69b889claireho}
65827f654740f2a26ad62a5c155af9199af9e69b889claireho
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
66085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Adopt a single format by format number.
66185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Do nothing if the format number is not less than the array count.
66227f654740f2a26ad62a5c155af9199af9e69b889claireho
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::adoptFormat(int32_t n, Format *newFormat) {
665b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<Format> p(newFormat);
666b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (n >= 0) {
667b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t formatNumber = 0;
668b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
669b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (n == formatNumber) {
670b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UErrorCode status = U_ZERO_ERROR;
671b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setCustomArgStartFormat(partIndex, p.orphan(), status);
672b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
673b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
674b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ++formatNumber;
675b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
68085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Adopt a single format by format name.
68185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Do nothing if there is no match of formatName.
68285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid
68327f654740f2a26ad62a5c155af9199af9e69b889clairehoMessageFormat::adoptFormat(const UnicodeString& formatName,
68485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                           Format* formatToAdopt,
68585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                           UErrorCode& status) {
686b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalPointer<Format> p(formatToAdopt);
687b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
688b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
689b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
690b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t argNumber = MessagePattern::validateArgumentName(formatName);
691b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) {
692b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;
69385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
69485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
695b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t partIndex = 0;
696b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (partIndex = nextTopLevelArgStart(partIndex)) >= 0 && U_SUCCESS(status);
697b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ) {
698b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (argNameMatches(partIndex + 1, formatName, argNumber)) {
699b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            Format* f;
700b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (p.isValid()) {
701b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                f = p.orphan();
702b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (formatToAdopt == NULL) {
703b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                f = NULL;
70485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else {
705b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                f = formatToAdopt->clone();
706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (f == NULL) {
707b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    status = U_MEMORY_ALLOCATION_ERROR;
708b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return;
709b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
71085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setCustomArgStartFormat(partIndex, f, status);
71285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
71385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
71485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
71585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
71685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// -------------------------------------
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Set a single format.
71885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Do nothing if the variable is not less than the array count.
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::setFormat(int32_t n, const Format& newFormat) {
721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (n >= 0) {
723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t formatNumber = 0;
724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (int32_t partIndex = 0;
725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho             (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (n == formatNumber) {
727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                Format* new_format = newFormat.clone();
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (new_format) {
729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    UErrorCode status = U_ZERO_ERROR;
730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    setCustomArgStartFormat(partIndex, new_format, status);
731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ++formatNumber;
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
73885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
73985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// -------------------------------------
74085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Get a single format by format name.
74185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Do nothing if the variable is not less than the array count.
74285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoFormat *
74385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoMessageFormat::getFormat(const UnicodeString& formatName, UErrorCode& status) {
744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status) || cachedFormatters == NULL) return NULL;
74585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t argNumber = MessagePattern::validateArgumentName(formatName);
747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) {
748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;
749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
75085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (argNameMatches(partIndex + 1, formatName, argNumber)) {
753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return getCachedFormatter(partIndex);
75485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
75585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
75685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return NULL;
75785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
75885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
75985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// -------------------------------------
76085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Set a single format by format name
76185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Do nothing if the variable is not less than the array count.
76285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid
76385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoMessageFormat::setFormat(const UnicodeString& formatName,
76485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                         const Format& newFormat,
76585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                         UErrorCode& status) {
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) return;
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t argNumber = MessagePattern::validateArgumentName(formatName);
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (argNumber < UMSGPAT_ARG_NAME_NOT_NUMBER) {
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;
77185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
77285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t partIndex = 0;
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        (partIndex = nextTopLevelArgStart(partIndex)) >= 0 && U_SUCCESS(status);
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ) {
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (argNameMatches(partIndex + 1, formatName, argNumber)) {
77785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            if (&newFormat == NULL) {
778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setCustomArgStartFormat(partIndex, NULL, status);
77985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            } else {
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                Format* new_format = newFormat.clone();
781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (new_format == NULL) {
782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    status = U_MEMORY_ALLOCATION_ERROR;
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    return;
784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                setCustomArgStartFormat(partIndex, new_format, status);
78685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
78785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
78885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
78985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
79085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Gets the format array.
793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst Format**
794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::getFormats(int32_t& cnt) const
795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // This old API returns an array (which we hold) of Format*
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pointers.  The array is valid up to the next call to any
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // method on this object.  We construct and resize an array
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // on demand that contains aliases to the subformats[i].format
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pointers.
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MessageFormat* t = const_cast<MessageFormat*> (this);
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    cnt = 0;
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (formatAliases == NULL) {
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        t->formatAliasesCapacity = (argTypeCount<10) ? 10 : argTypeCount;
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Format** a = (Format**)
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_malloc(sizeof(Format*) * formatAliasesCapacity);
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (a == NULL) {
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            t->formatAliasesCapacity = 0;
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
81127f654740f2a26ad62a5c155af9199af9e69b889claireho        t->formatAliases = a;
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (argTypeCount > formatAliasesCapacity) {
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Format** a = (Format**)
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uprv_realloc(formatAliases, sizeof(Format*) * argTypeCount);
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (a == NULL) {
816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            t->formatAliasesCapacity = 0;
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return NULL;
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        t->formatAliases = a;
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        t->formatAliasesCapacity = argTypeCount;
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        t->formatAliases[cnt++] = getCachedFormatter(partIndex);
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return (const Format**)formatAliases;
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
82927f654740f2a26ad62a5c155af9199af9e69b889claireho
83085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString MessageFormat::getArgName(int32_t partIndex) {
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const MessagePattern::Part& part = msgPattern.getPart(partIndex);
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (part.getType() == UMSGPAT_PART_TYPE_ARG_NAME) {
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return msgPattern.getSubstring(part);
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString temp;
837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return itos(part.getValue(), temp);
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
84185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoStringEnumeration*
84285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoMessageFormat::getFormatNames(UErrorCode& status) {
84385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_FAILURE(status))  return NULL;
84427f654740f2a26ad62a5c155af9199af9e69b889claireho
84585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    UVector *fFormatNames = new UVector(status);
84685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_FAILURE(status)) {
84785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        status = U_MEMORY_ALLOCATION_ERROR;
84885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return NULL;
84985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
850103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    fFormatNames->setDeleter(uprv_deleteUObject);
851b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t partIndex = 0; (partIndex = nextTopLevelArgStart(partIndex)) >= 0;) {
85354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        fFormatNames->addElement(new UnicodeString(getArgName(partIndex + 1)), status);
85485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
85585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
85685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    StringEnumeration* nameEnumerator = new FormatNameEnumeration(fFormatNames, status);
85785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return nameEnumerator;
85885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
85985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Formats the source Formattable array and copy into the result buffer.
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Ignore the FieldPosition result for error checking.
86327f654740f2a26ad62a5c155af9199af9e69b889claireho
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::format(const Formattable* source,
86627f654740f2a26ad62a5c155af9199af9e69b889claireho                      int32_t cnt,
86727f654740f2a26ad62a5c155af9199af9e69b889claireho                      UnicodeString& appendTo,
86827f654740f2a26ad62a5c155af9199af9e69b889claireho                      FieldPosition& ignore,
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      UErrorCode& success) const
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return format(source, NULL, cnt, appendTo, &ignore, success);
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
87327f654740f2a26ad62a5c155af9199af9e69b889claireho
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Internally creates a MessageFormat instance based on the
87627f654740f2a26ad62a5c155af9199af9e69b889claireho// pattern and formats the arguments Formattable array and
877ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// copy into the appendTo buffer.
87827f654740f2a26ad62a5c155af9199af9e69b889claireho
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::format(  const UnicodeString& pattern,
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        const Formattable* arguments,
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        int32_t cnt,
88327f654740f2a26ad62a5c155af9199af9e69b889claireho                        UnicodeString& appendTo,
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        UErrorCode& success)
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    MessageFormat temp(pattern, success);
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return temp.format(arguments, NULL, cnt, appendTo, NULL, success);
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
88927f654740f2a26ad62a5c155af9199af9e69b889claireho
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
89127f654740f2a26ad62a5c155af9199af9e69b889claireho// Formats the source Formattable object and copy into the
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// appendTo buffer.  The Formattable object must be an array
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// of Formattable instances, returns error otherwise.
89427f654740f2a26ad62a5c155af9199af9e69b889claireho
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
89627f654740f2a26ad62a5c155af9199af9e69b889clairehoMessageFormat::format(const Formattable& source,
89727f654740f2a26ad62a5c155af9199af9e69b889claireho                      UnicodeString& appendTo,
89827f654740f2a26ad62a5c155af9199af9e69b889claireho                      FieldPosition& ignore,
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                      UErrorCode& success) const
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
90127f654740f2a26ad62a5c155af9199af9e69b889claireho    if (U_FAILURE(success))
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return appendTo;
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (source.getType() != Formattable::kArray) {
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = U_ILLEGAL_ARGUMENT_ERROR;
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return appendTo;
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t cnt;
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const Formattable* tmpPtr = source.getArray(cnt);
909b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return format(tmpPtr, NULL, cnt, appendTo, &ignore, success);
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
91185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
91285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUnicodeString&
91385bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoMessageFormat::format(const UnicodeString* argumentNames,
91485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      const Formattable* arguments,
91585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      int32_t count,
91685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      UnicodeString& appendTo,
91785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      UErrorCode& success) const {
918b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return format(arguments, argumentNames, count, appendTo, NULL, success);
91985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
92085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
921b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Does linear search to find the match for an ArgName.
922b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst Formattable* MessageFormat::getArgFromListByName(const Formattable* arguments,
923b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                       const UnicodeString *argumentNames,
924b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                       int32_t cnt, UnicodeString& name) const {
925b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = 0; i < cnt; ++i) {
926b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (0 == argumentNames[i].compare(name)) {
927b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return arguments + i;
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
929b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
930b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
93185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
93285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
93585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoMessageFormat::format(const Formattable* arguments,
93685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                      const UnicodeString *argumentNames,
93727f654740f2a26ad62a5c155af9199af9e69b889claireho                      int32_t cnt,
93827f654740f2a26ad62a5c155af9199af9e69b889claireho                      UnicodeString& appendTo,
939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                      FieldPosition* pos,
940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                      UErrorCode& status) const {
941b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return appendTo;
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
94427f654740f2a26ad62a5c155af9199af9e69b889claireho
945b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeStringAppendable usapp(appendTo);
946b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    AppendableWrapper app(usapp);
947b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    format(0, 0.0, arguments, argumentNames, cnt, app, pos, status);
948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return appendTo;
949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
950b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
951b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// if argumentNames is NULL, this means arguments is a numeric array.
952b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// arguments can not be NULL.
953b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::format(int32_t msgStart, double pluralNumber,
954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                           const Formattable* arguments,
955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                           const UnicodeString *argumentNames,
956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                           int32_t cnt,
957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                           AppendableWrapper& appendTo,
958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                           FieldPosition* ignore,
959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                           UErrorCode& success) const {
960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(success)) {
961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
96285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
96327f654740f2a26ad62a5c155af9199af9e69b889claireho
964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString& msgString = msgPattern.getPatternString();
965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prevIndex = msgPattern.getPart(msgStart).getLimit();
966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = msgStart + 1; U_SUCCESS(success) ; ++i) {
967b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part* part = &msgPattern.getPart(i);
968b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UMessagePatternPartType type = part->getType();
969b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t index = part->getIndex();
970b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.append(msgString, prevIndex, index - prevIndex);
971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) {
972b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
97385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
974b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        prevIndex = part->getLimit();
975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (type == UMSGPAT_PART_TYPE_REPLACE_NUMBER) {
976b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const NumberFormat* nf = getDefaultNumberFormat(success);
977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            appendTo.formatAndAppend(nf, Formattable(pluralNumber), success);
978b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;
979b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
980b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (type != UMSGPAT_PART_TYPE_ARG_START) {
981b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;
982b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
983b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t argLimit = msgPattern.getLimitPartIndex(i);
984b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UMessagePatternArgType argType = part->getArgType();
985b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part = &msgPattern.getPart(++i);
986b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const Formattable* arg;
987b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString noArg;
988b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (argumentNames == NULL) {
989b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t argNumber = part->getValue();  // ARG_NUMBER
990b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (0 <= argNumber && argNumber < cnt) {
991b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                arg = arguments + argNumber;
992b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
993b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                arg = NULL;
994b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                noArg.append(LEFT_CURLY_BRACE);
995b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                itos(argNumber, noArg);
996b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                noArg.append(RIGHT_CURLY_BRACE);
99785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
999b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString key;
1000b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (part->getType() == UMSGPAT_PART_TYPE_ARG_NAME) {
1001b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                key = msgPattern.getSubstring(*part);
1002b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else /* UMSGPAT_PART_TYPE_ARG_NUMBER */ {
1003b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                itos(part->getValue(), key);
1004b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1005b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            arg = getArgFromListByName(arguments, argumentNames, cnt, key);
1006b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (arg == NULL) {
1007b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                noArg.append(LEFT_CURLY_BRACE);
1008b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                noArg.append(key);
1009b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                noArg.append(RIGHT_CURLY_BRACE);
101085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1012b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ++i;
1013b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t prevDestLength = appendTo.length();
1014b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const Format* formatter = NULL;
1015b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!noArg.isEmpty()) {
1016b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            appendTo.append(noArg);
1017b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (arg == NULL) {
1018b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            appendTo.append(NULL_STRING, 4);
1019b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if ((formatter = getCachedFormatter(i -2))) {
1020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Handles all ArgType.SIMPLE, and formatters from setFormat() and its siblings.
1021b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (dynamic_cast<const ChoiceFormat*>(formatter) ||
1022b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                dynamic_cast<const PluralFormat*>(formatter) ||
1023b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                dynamic_cast<const SelectFormat*>(formatter)) {
1024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // We only handle nested formats here if they were provided via
1025b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // setFormat() or its siblings. Otherwise they are not cached and instead
1026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                // handled below according to argType.
1027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UnicodeString subMsgString;
1028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                formatter->format(*arg, subMsgString, success);
1029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (subMsgString.indexOf(LEFT_CURLY_BRACE) >= 0 ||
1030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    (subMsgString.indexOf(SINGLE_QUOTE) >= 0 && !MessageImpl::jdkAposMode(msgPattern))
1031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ) {
1032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    MessageFormat subMsgFormat(subMsgString, fLocale, success);
1033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    subMsgFormat.format(0, 0, arguments, argumentNames, cnt, appendTo, ignore, success);
1034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                } else {
1035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    appendTo.append(subMsgString);
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1037b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
1038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                appendTo.formatAndAppend(formatter, *arg, success);
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (argType == UMSGPAT_ARG_TYPE_NONE || (cachedFormatters && uhash_iget(cachedFormatters, i - 2))) {
1041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // We arrive here if getCachedFormatter returned NULL, but there was actually an element in the hash table.
1042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // This can only happen if the hash table contained a DummyFormat, so the if statement above is a check
1043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // for the hash table containind DummyFormat.
1044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (arg->isNumeric()) {
1045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                const NumberFormat* nf = getDefaultNumberFormat(success);
1046b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                appendTo.formatAndAppend(nf, *arg, success);
1047b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else if (arg->getType() == Formattable::kDate) {
1048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                const DateFormat* df = getDefaultDateFormat(success);
1049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                appendTo.formatAndAppend(df, *arg, success);
1050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
1051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                appendTo.append(arg->getString(success));
1052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (argType == UMSGPAT_ARG_TYPE_CHOICE) {
1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!arg->isNumeric()) {
1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                success = U_ILLEGAL_ARGUMENT_ERROR;
1056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // We must use the Formattable::getDouble() variant with the UErrorCode parameter
1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // because only this one converts non-double numeric types to double.
1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const double number = arg->getDouble(success);
1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t subMsgStart = ChoiceFormat::findSubMessage(msgPattern, i, number);
1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formatComplexSubMessage(subMsgStart, 0, arguments, argumentNames,
1063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    cnt, appendTo, success);
106454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        } else if (UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType)) {
1065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!arg->isNumeric()) {
1066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                success = U_ILLEGAL_ARGUMENT_ERROR;
1067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
1068b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
106954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            const PluralFormat::PluralSelector &selector =
107054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                argType == UMSGPAT_ARG_TYPE_PLURAL ? pluralProvider : ordinalProvider;
1071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // We must use the Formattable::getDouble() variant with the UErrorCode parameter
1072b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // because only this one converts non-double numeric types to double.
1073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            double number = arg->getDouble(success);
107454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius            int32_t subMsgStart = PluralFormat::findSubMessage(msgPattern, i, selector, number,
1075b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                               success);
1076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            double offset = msgPattern.getPluralOffset(i);
1077b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formatComplexSubMessage(subMsgStart, number-offset, arguments, argumentNames,
1078b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    cnt, appendTo, success);
1079b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (argType == UMSGPAT_ARG_TYPE_SELECT) {
1080b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t subMsgStart = SelectFormat::findSubMessage(msgPattern, i, arg->getString(success), success);
1081b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formatComplexSubMessage(subMsgStart, 0, arguments, argumentNames,
1082b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                    cnt, appendTo, success);
1083b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1084b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // This should never happen.
1085b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            success = U_INTERNAL_PROGRAM_ERROR;
1086b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ignore = updateMetaData(appendTo, prevDestLength, ignore, arg);
1089b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        prevIndex = msgPattern.getPart(argLimit).getLimit();
1090b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        i = argLimit;
1091b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1092b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1094b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::formatComplexSubMessage(int32_t msgStart,
1096b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            double pluralNumber,
1097b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            const Formattable* arguments,
1098b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            const UnicodeString *argumentNames,
1099b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            int32_t cnt,
1100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            AppendableWrapper& appendTo,
1101b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                            UErrorCode& success) const {
1102b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(success)) {
1103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!MessageImpl::jdkAposMode(msgPattern)) {
1107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        format(msgStart, pluralNumber, arguments, argumentNames, cnt, appendTo, NULL, success);
1108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // JDK compatibility mode: (see JDK MessageFormat.format() API docs)
1112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // - remove SKIP_SYNTAX; that is, remove half of the apostrophes
1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // - if the result string contains an open curly brace '{' then
1114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   instantiate a temporary MessageFormat object and format again;
1115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    //   otherwise just append the result string
1116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString& msgString = msgPattern.getPatternString();
1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString sb;
1118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prevIndex = msgPattern.getPart(msgStart).getLimit();
1119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = msgStart;;) {
1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part& part = msgPattern.getPart(++i);
1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UMessagePatternPartType type = part.getType();
1122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t index = part.getIndex();
1123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) {
1124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sb.append(msgString, prevIndex, index - prevIndex);
1125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (type == UMSGPAT_PART_TYPE_REPLACE_NUMBER || type == UMSGPAT_PART_TYPE_SKIP_SYNTAX) {
1127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sb.append(msgString, prevIndex, index - prevIndex);
1128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (type == UMSGPAT_PART_TYPE_REPLACE_NUMBER) {
1129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                const NumberFormat* nf = getDefaultNumberFormat(success);
1130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                sb.append(nf->format(pluralNumber, sb, success));
1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex = part.getLimit();
1133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if (type == UMSGPAT_PART_TYPE_ARG_START) {
1134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sb.append(msgString, prevIndex, index - prevIndex);
1135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex = index;
1136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            i = msgPattern.getLimitPartIndex(i);
1137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            index = msgPattern.getPart(i).getLimit();
1138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            MessageImpl::appendReducedApostrophes(msgString, prevIndex, index, sb);
1139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex = index;
1140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (sb.indexOf(LEFT_CURLY_BRACE) >= 0) {
1143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString emptyPattern;  // gcc 3.3.3 fails with "UnicodeString()" as the first parameter.
1144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        MessageFormat subMsgFormat(emptyPattern, fLocale, success);
1145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        subMsgFormat.applyPattern(sb, UMSGPAT_APOS_DOUBLE_REQUIRED, NULL, success);
1146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        subMsgFormat.format(0, 0, arguments, argumentNames, cnt, appendTo, NULL, success);
1147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else {
1148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        appendTo.append(sb);
1149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString MessageFormat::getLiteralStringUntilNextArgument(int32_t from) const {
1154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString& msgString=msgPattern.getPatternString();
1155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prevIndex=msgPattern.getPart(from).getLimit();
1156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString b;
1157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = from + 1; ; ++i) {
1158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part& part = msgPattern.getPart(i);
1159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UMessagePatternPartType type=part.getType();
1160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t index=part.getIndex();
1161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        b.append(msgString, prevIndex, index - prevIndex);
1162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(type==UMSGPAT_PART_TYPE_ARG_START || type==UMSGPAT_PART_TYPE_MSG_LIMIT) {
1163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return b;
1164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Unexpected Part "part" in parsed message.
1166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(type==UMSGPAT_PART_TYPE_SKIP_SYNTAX || type==UMSGPAT_PART_TYPE_INSERT_CHAR);
1167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        prevIndex=part.getLimit();
1168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1169b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1170b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1171b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1172b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoFieldPosition* MessageFormat::updateMetaData(AppendableWrapper& /*dest*/, int32_t /*prevLength*/,
1173b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                             FieldPosition* /*fp*/, const Formattable* /*argId*/) const {
1174b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Unlike in Java, there are no field attributes defined for MessageFormat. Do nothing.
1175b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return NULL;
1176b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    /*
1177b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      if (fp != NULL && Field.ARGUMENT.equals(fp.getFieldAttribute())) {
1178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          fp->setBeginIndex(prevLength);
1179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          fp->setEndIndex(dest.get_length());
1180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho          return NULL;
1181b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      }
1182b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho      return fp;
1183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    */
1184b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::copyObjects(const MessageFormat& that, UErrorCode& ec) {
1187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Deep copy pointer fields.
1188b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // We need not copy the formatAliases because they are re-filled
1189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // in each getFormats() call.
1190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // The defaultNumberFormat, defaultDateFormat and pluralProvider.rules
1191b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // also get created on demand.
1192b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    argTypeCount = that.argTypeCount;
1193b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (argTypeCount > 0) {
1194b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (!allocateArgTypes(argTypeCount, ec)) {
1195b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return;
1196b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1197b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uprv_memcpy(argTypes, that.argTypes, argTypeCount * sizeof(argTypes[0]));
1198b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1199b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cachedFormatters != NULL) {
1200b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(cachedFormatters);
1201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1202b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (customFormatArgStarts != NULL) {
1203b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(customFormatArgStarts);
1204b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (that.cachedFormatters) {
1206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (cachedFormatters == NULL) {
1207b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            cachedFormatters=uhash_open(uhash_hashLong, uhash_compareLong,
1208b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                        equalFormatsForHash, &ec);
1209b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(ec)) {
1210b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            uhash_setValueDeleter(cachedFormatters, uprv_deleteUObject);
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t count = uhash_count(that.cachedFormatters);
1216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t pos, idx;
1217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (idx = 0, pos = -1; idx < count && U_SUCCESS(ec); ++idx) {
1218b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UHashElement* cur = uhash_nextElement(that.cachedFormatters, &pos);
1219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            Format* newFormat = ((Format*)(cur->value.pointer))->clone();
1220b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (newFormat) {
1221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uhash_iput(cachedFormatters, cur->key.integer, newFormat, &ec);
1222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
1223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ec = U_MEMORY_ALLOCATION_ERROR;
1224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return;
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (that.customFormatArgStarts) {
1229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (customFormatArgStarts == NULL) {
1230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            customFormatArgStarts=uhash_open(uhash_hashLong, uhash_compareLong,
1231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                              NULL, &ec);
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const int32_t count = uhash_count(that.customFormatArgStarts);
1234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t pos, idx;
1235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        for (idx = 0, pos = -1; idx < count && U_SUCCESS(ec); ++idx) {
1236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const UHashElement* cur = uhash_nextElement(that.customFormatArgStarts, &pos);
1237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uhash_iputi(customFormatArgStarts, cur->key.integer, cur->value.integer, &ec);
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormattable*
1244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessageFormat::parse(int32_t msgStart,
1245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     const UnicodeString& source,
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     ParsePosition& pos,
1247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     int32_t& count,
1248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     UErrorCode& ec) const {
1249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    count = 0;
1250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
1251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        pos.setErrorIndex(pos.getIndex());
1252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // parse() does not work with named arguments.
1255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (msgPattern.hasNamedArguments()) {
1256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ec = U_ARGUMENT_TYPE_MISMATCH;
1257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        pos.setErrorIndex(pos.getIndex());
1258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LocalArray<Formattable> resultArray(new Formattable[argTypeCount ? argTypeCount : 1]);
1261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UnicodeString& msgString=msgPattern.getPatternString();
1262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t prevIndex=msgPattern.getPart(msgStart).getLimit();
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t sourceOffset = pos.getIndex();
1264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ParsePosition tempStatus(0);
1265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for(int32_t i=msgStart+1; ; ++i) {
1267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UBool haveArgResult = FALSE;
1268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part* part=&msgPattern.getPart(i);
1269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UMessagePatternPartType type=part->getType();
1270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t index=part->getIndex();
1271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Make sure the literal string matches.
1272b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t len = index - prevIndex;
1273b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (len == 0 || (0 == msgString.compare(prevIndex, len, source, sourceOffset, len))) {
1274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            sourceOffset += len;
1275b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex += len;
1276b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1277b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            pos.setErrorIndex(sourceOffset);
1278b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL; // leave index as is to signal error
127927f654740f2a26ad62a5c155af9199af9e69b889claireho        }
1280b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(type==UMSGPAT_PART_TYPE_MSG_LIMIT) {
1281b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Things went well! Done.
1282b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            pos.setIndex(sourceOffset);
1283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return resultArray.orphan();
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(type==UMSGPAT_PART_TYPE_SKIP_SYNTAX || type==UMSGPAT_PART_TYPE_INSERT_CHAR) {
1286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            prevIndex=part->getLimit();
1287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;
1288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // We do not support parsing Plural formats. (No REPLACE_NUMBER here.)
1290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // Unexpected Part "part" in parsed message.
1291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        U_ASSERT(type==UMSGPAT_PART_TYPE_ARG_START);
1292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t argLimit=msgPattern.getLimitPartIndex(i);
1293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UMessagePatternArgType argType=part->getArgType();
1295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part=&msgPattern.getPart(++i);
1296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t argNumber = part->getValue();  // ARG_NUMBER
1297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UnicodeString key;
1298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ++i;
1299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const Format* formatter = NULL;
1300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Formattable& argResult = resultArray[argNumber];
1301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if(cachedFormatters!=NULL && (formatter = getCachedFormatter(i - 2))!=NULL) {
1303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Just parse using the formatter.
1304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            tempStatus.setIndex(sourceOffset);
1305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formatter->parseObject(source, argResult, tempStatus);
1306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tempStatus.getIndex() == sourceOffset) {
1307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                pos.setErrorIndex(sourceOffset);
1308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return NULL; // leave index as is to signal error
1309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sourceOffset = tempStatus.getIndex();
1311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            haveArgResult = TRUE;
1312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(
1313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            argType==UMSGPAT_ARG_TYPE_NONE || (cachedFormatters && uhash_iget(cachedFormatters, i -2))) {
1314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // We arrive here if getCachedFormatter returned NULL, but there was actually an element in the hash table.
1315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // This can only happen if the hash table contained a DummyFormat, so the if statement above is a check
1316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // for the hash table containind DummyFormat.
1317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Match as a string.
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // if at end, use longest possible match
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // otherwise uses first match to intervening string
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // does NOT recursively try all possibilities
1322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString stringAfterArgument = getLiteralStringUntilNextArgument(argLimit);
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t next;
1324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (!stringAfterArgument.isEmpty()) {
1325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                next = source.indexOf(stringAfterArgument, sourceOffset);
1326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                next = source.length();
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (next < 0) {
1330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                pos.setErrorIndex(sourceOffset);
1331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return NULL; // leave index as is to signal error
1332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
1333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UnicodeString strValue(source.tempSubString(sourceOffset, next - sourceOffset));
1334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                UnicodeString compValue;
1335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                compValue.append(LEFT_CURLY_BRACE);
1336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                itos(argNumber, compValue);
1337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                compValue.append(RIGHT_CURLY_BRACE);
1338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (0 != strValue.compare(compValue)) {
1339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    argResult.setString(strValue);
1340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    haveArgResult = TRUE;
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                sourceOffset = next;
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else if(argType==UMSGPAT_ARG_TYPE_CHOICE) {
1345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            tempStatus.setIndex(sourceOffset);
1346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            double choiceResult = ChoiceFormat::parseArgument(msgPattern, i, source, tempStatus);
1347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (tempStatus.getIndex() == sourceOffset) {
1348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                pos.setErrorIndex(sourceOffset);
1349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return NULL; // leave index as is to signal error
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            argResult.setDouble(choiceResult);
1352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            haveArgResult = TRUE;
1353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            sourceOffset = tempStatus.getIndex();
135454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        } else if(UMSGPAT_ARG_TYPE_HAS_PLURAL_STYLE(argType) || argType==UMSGPAT_ARG_TYPE_SELECT) {
1355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Parsing not supported.
1356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ec = U_UNSUPPORTED_ERROR;
1357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
1358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // This should never happen.
1360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ec = U_INTERNAL_PROGRAM_ERROR;
1361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1363b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (haveArgResult && count <= argNumber) {
1364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            count = argNumber + 1;
1365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1366b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        prevIndex=msgPattern.getPart(argLimit).getLimit();
1367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        i=argLimit;
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// -------------------------------------
1371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Parses the source pattern and returns the Formattable objects array,
1372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// the array count and the ending parse position.  The caller of this method
1373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// owns the array.
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoFormattable*
1376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessageFormat::parse(const UnicodeString& source,
1377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     ParsePosition& pos,
1378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                     int32_t& count) const {
1379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
1380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return parse(0, source, pos, count, ec);
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
138227f654740f2a26ad62a5c155af9199af9e69b889claireho
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
138427f654740f2a26ad62a5c155af9199af9e69b889claireho// Parses the source string and returns the array of
138527f654740f2a26ad62a5c155af9199af9e69b889claireho// Formattable objects and the array count.  The caller
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// owns the returned array.
138727f654740f2a26ad62a5c155af9199af9e69b889claireho
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormattable*
138927f654740f2a26ad62a5c155af9199af9e69b889clairehoMessageFormat::parse(const UnicodeString& source,
1390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     int32_t& cnt,
1391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     UErrorCode& success) const
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (msgPattern.hasNamedArguments()) {
139485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        success = U_ARGUMENT_TYPE_MISMATCH;
139527f654740f2a26ad62a5c155af9199af9e69b889claireho        return NULL;
139685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition status(0);
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Calls the actual implementation method and starts
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // from zero offset of the source text.
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Formattable* result = parse(source, status, cnt);
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (status.getIndex() == 0) {
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        success = U_MESSAGE_PARSE_ERROR;
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete[] result;
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
140827f654740f2a26ad62a5c155af9199af9e69b889claireho
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Parses the source text and copy into the result buffer.
141127f654740f2a26ad62a5c155af9199af9e69b889claireho
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::parseObject( const UnicodeString& source,
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            Formattable& result,
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            ParsePosition& status) const
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t cnt = 0;
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Formattable* tmpResult = parse(source, status, cnt);
141927f654740f2a26ad62a5c155af9199af9e69b889claireho    if (tmpResult != NULL)
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result.adoptArray(tmpResult, cnt);
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
142227f654740f2a26ad62a5c155af9199af9e69b889claireho
142327f654740f2a26ad62a5c155af9199af9e69b889clairehoUnicodeString
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::autoQuoteApostrophe(const UnicodeString& pattern, UErrorCode& status) {
1425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString result;
1426b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
1427b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t plen = pattern.length();
1428b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const UChar* pat = pattern.getBuffer();
1429b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t blen = plen * 2 + 1; // space for null termination, convenience
1430b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UChar* buf = result.getBuffer(blen);
1431b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (buf == NULL) {
1432b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_MEMORY_ALLOCATION_ERROR;
1433b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1434b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t len = umsg_autoQuoteApostrophe(pat, plen, buf, blen, &status);
1435b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            result.releaseBuffer(U_SUCCESS(status) ? len : 0);
1436b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1437b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1438b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1439b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result.setToBogus();
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1441b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return result;
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// -------------------------------------
1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic Format* makeRBNF(URBNFRuleSetTag tag, const Locale& locale, const UnicodeString& defaultRuleSet, UErrorCode& ec) {
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    RuleBasedNumberFormat* fmt = new RuleBasedNumberFormat(tag, locale, ec);
144885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (fmt == NULL) {
144985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ec = U_MEMORY_ALLOCATION_ERROR;
145085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else if (U_SUCCESS(ec) && defaultRuleSet.length() > 0) {
145185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UErrorCode localStatus = U_ZERO_ERROR; // ignore unrecognized default rule set
145285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        fmt->setDefaultRuleSet(defaultRuleSet, localStatus);
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return fmt;
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
145627f654740f2a26ad62a5c155af9199af9e69b889claireho
1457b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::cacheExplicitFormats(UErrorCode& status) {
1458b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (cachedFormatters != NULL) {
1463b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(cachedFormatters);
146485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1465b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (customFormatArgStarts != NULL) {
1466b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uhash_removeAll(customFormatArgStarts);
1467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1468b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1469b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // The last two "parts" can at most be ARG_LIMIT and MSG_LIMIT
1470b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // which we need not examine.
1471b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t limit = msgPattern.countParts() - 2;
1472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    argTypeCount = 0;
1473b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // We also need not look at the first two "parts"
1474b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // (at most MSG_START and ARG_START) in this loop.
1475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // We determine the argTypeCount first so that we can allocateArgTypes
1476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // so that the next loop can set argTypes[argNumber].
1477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // (This is for the C API which needs the argTypes to read its va_arg list.)
1478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = 2; i < limit && U_SUCCESS(status); ++i) {
1479b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part& part = msgPattern.getPart(i);
1480b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (part.getType() == UMSGPAT_PART_TYPE_ARG_NUMBER) {
1481b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const int argNumber = part.getValue();
1482b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (argNumber >= argTypeCount) {
1483b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                argTypeCount = argNumber + 1;
1484b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
148585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1487b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (!allocateArgTypes(argTypeCount, status)) {
1488b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return;
1489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Set all argTypes to kObject, as a "none" value, for lack of any better value.
1491b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // We never use kObject for real arguments.
149254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    // We use it as "no argument yet" for the check for hasArgTypeConflicts.
1493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = 0; i < argTypeCount; ++i) {
1494b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        argTypes[i] = Formattable::kObject;
1495b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1496b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    hasArgTypeConflicts = FALSE;
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1498b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // This loop starts at part index 1 because we do need to examine
1499b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // ARG_START parts. (But we can ignore the MSG_START.)
1500b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    for (int32_t i = 1; i < limit && U_SUCCESS(status); ++i) {
1501b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        const MessagePattern::Part* part = &msgPattern.getPart(i);
1502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (part->getType() != UMSGPAT_PART_TYPE_ARG_START) {
1503b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            continue;
1504b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1505b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        UMessagePatternArgType argType = part->getArgType();
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1507b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t argNumber = -1;
1508b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        part = &msgPattern.getPart(i + 1);
1509b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (part->getType() == UMSGPAT_PART_TYPE_ARG_NUMBER) {
1510b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            argNumber = part->getValue();
1511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        Formattable::Type formattableType;
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        switch (argType) {
1515b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UMSGPAT_ARG_TYPE_NONE:
1516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formattableType = Formattable::kString;
1517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UMSGPAT_ARG_TYPE_SIMPLE: {
1519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t index = i;
1520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            i += 2;
1521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString explicitType = msgPattern.getSubstring(msgPattern.getPart(i++));
1522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UnicodeString style;
1523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if ((part = &msgPattern.getPart(i))->getType() == UMSGPAT_PART_TYPE_ARG_STYLE) {
1524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                style = msgPattern.getSubstring(*part);
1525b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ++i;
1526b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1527b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UParseError parseError;
1528b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            Format* formatter = createAppropriateFormat(explicitType, style, formattableType, parseError, status);
1529b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            setArgStartFormat(index, formatter, status);
1530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UMSGPAT_ARG_TYPE_CHOICE:
1533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UMSGPAT_ARG_TYPE_PLURAL:
153454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        case UMSGPAT_ARG_TYPE_SELECTORDINAL:
1535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formattableType = Formattable::kDouble;
1536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UMSGPAT_ARG_TYPE_SELECT:
1538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formattableType = Formattable::kString;
1539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        default:
1541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_INTERNAL_PROGRAM_ERROR;  // Should be unreachable.
1542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formattableType = Formattable::kString;
1543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
1544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (argNumber != -1) {
1546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (argTypes[argNumber] != Formattable::kObject && argTypes[argNumber] != formattableType) {
1547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                hasArgTypeConflicts = TRUE;
1548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
1549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            argTypes[argNumber] = formattableType;
1550b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1551b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoFormat* MessageFormat::createAppropriateFormat(UnicodeString& type, UnicodeString& style,
1556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                               Formattable::Type& formattableType, UParseError& parseError,
1557b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                               UErrorCode& ec) {
1558b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
1559b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1560b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1561b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    Format* fmt = NULL;
1562b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t typeID, styleID;
1563b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    DateFormat::EStyle date_style;
1564b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1565b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    switch (typeID = findKeyword(type, TYPE_IDS)) {
1566b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case 0: // number
1567b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formattableType = Formattable::kDouble;
1568b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        switch (findKeyword(style, NUMBER_STYLE_IDS)) {
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 0: // default
1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = NumberFormat::createInstance(fLocale, ec);
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 1: // currency
1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = NumberFormat::createCurrencyInstance(fLocale, ec);
1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 2: // percent
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = NumberFormat::createPercentInstance(fLocale, ec);
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        case 3: // integer
1579b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            formattableType = Formattable::kLong;
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = createIntegerFormat(fLocale, ec);
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        default: // pattern
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            fmt = NumberFormat::createInstance(fLocale, ec);
158427f654740f2a26ad62a5c155af9199af9e69b889claireho            if (fmt) {
158527f654740f2a26ad62a5c155af9199af9e69b889claireho                DecimalFormat* decfmt = dynamic_cast<DecimalFormat*>(fmt);
158627f654740f2a26ad62a5c155af9199af9e69b889claireho                if (decfmt != NULL) {
1587b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    decfmt->applyPattern(style,parseError,ec);
158827f654740f2a26ad62a5c155af9199af9e69b889claireho                }
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1594b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case 1: // date
1595b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case 2: // time
1596b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formattableType = Formattable::kDate;
1597b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        styleID = findKeyword(style, DATE_STYLE_IDS);
1598b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        date_style = (styleID >= 0) ? DATE_STYLES[styleID] : DateFormat::kDefault;
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1600b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (typeID == 1) {
1601b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fmt = DateFormat::createDateInstance(date_style, fLocale);
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1603b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            fmt = DateFormat::createTimeInstance(date_style, fLocale);
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
160627f654740f2a26ad62a5c155af9199af9e69b889claireho        if (styleID < 0 && fmt != NULL) {
160727f654740f2a26ad62a5c155af9199af9e69b889claireho            SimpleDateFormat* sdtfmt = dynamic_cast<SimpleDateFormat*>(fmt);
160827f654740f2a26ad62a5c155af9199af9e69b889claireho            if (sdtfmt != NULL) {
1609b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                sdtfmt->applyPattern(style);
161027f654740f2a26ad62a5c155af9199af9e69b889claireho            }
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1614b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case 3: // spellout
1615b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formattableType = Formattable::kDouble;
1616b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fmt = makeRBNF(URBNF_SPELLOUT, fLocale, style, ec);
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1618b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case 4: // ordinal
1619b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formattableType = Formattable::kDouble;
1620b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fmt = makeRBNF(URBNF_ORDINAL, fLocale, style, ec);
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1622b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    case 5: // duration
1623b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formattableType = Formattable::kDouble;
1624b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        fmt = makeRBNF(URBNF_DURATION, fLocale, style, ec);
162585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        break;
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default:
1627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        formattableType = Formattable::kString;
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ec = U_ILLEGAL_ARGUMENT_ERROR;
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        break;
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return fmt;
1633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
163427f654740f2a26ad62a5c155af9199af9e69b889claireho
1635b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1636b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho//-------------------------------------
163727f654740f2a26ad62a5c155af9199af9e69b889claireho// Finds the string, s, in the string array, list.
163827f654740f2a26ad62a5c155af9199af9e69b889clairehoint32_t MessageFormat::findKeyword(const UnicodeString& s,
1639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                   const UChar * const *list)
1640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1641b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (s.isEmpty()) {
1642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0; // default
1643b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1645b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t length = s.length();
1646b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *ps = PatternProps::trimWhiteSpace(s.getBuffer(), length);
1647b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UnicodeString buffer(FALSE, ps, length);
1648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Trims the space characters and turns all characters
1649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // in s to lower case.
1650b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    buffer.toLower("");
1651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t i = 0; list[i]; ++i) {
1652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!buffer.compare(list[i], u_strlen(list[i]))) {
1653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return i;
1654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -1;
1657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
165827f654740f2a26ad62a5c155af9199af9e69b889claireho
1659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Convenience method that ought to be in NumberFormat
1661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
166227f654740f2a26ad62a5c155af9199af9e69b889clairehoNumberFormat*
1663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMessageFormat::createIntegerFormat(const Locale& locale, UErrorCode& status) const {
1664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NumberFormat *temp = NumberFormat::createInstance(locale, status);
166527f654740f2a26ad62a5c155af9199af9e69b889claireho    DecimalFormat *temp2;
166627f654740f2a26ad62a5c155af9199af9e69b889claireho    if (temp != NULL && (temp2 = dynamic_cast<DecimalFormat*>(temp)) != NULL) {
1667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        temp2->setMaximumFractionDigits(0);
1668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        temp2->setDecimalSeparatorAlwaysShown(FALSE);
1669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        temp2->setParseIntegerOnly(TRUE);
1670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return temp;
1673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return the default number format.  Used to format a numeric
1677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * argument when subformats[i].format is NULL.  Returns NULL
1678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * on failure.
1679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
1680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Semantically const but may modify *this.
1681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst NumberFormat* MessageFormat::getDefaultNumberFormat(UErrorCode& ec) const {
1683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (defaultNumberFormat == NULL) {
1684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        MessageFormat* t = (MessageFormat*) this;
1685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        t->defaultNumberFormat = NumberFormat::createInstance(fLocale, ec);
168627f654740f2a26ad62a5c155af9199af9e69b889claireho        if (U_FAILURE(ec)) {
1687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete t->defaultNumberFormat;
1688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            t->defaultNumberFormat = NULL;
1689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (t->defaultNumberFormat == NULL) {
1690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ec = U_MEMORY_ALLOCATION_ERROR;
1691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return defaultNumberFormat;
1694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1695ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Return the default date format.  Used to format a date
1698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * argument when subformats[i].format is NULL.  Returns NULL
1699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * on failure.
1700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru *
1701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Semantically const but may modify *this.
1702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
1703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst DateFormat* MessageFormat::getDefaultDateFormat(UErrorCode& ec) const {
1704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (defaultDateFormat == NULL) {
1705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        MessageFormat* t = (MessageFormat*) this;
1706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        t->defaultDateFormat = DateFormat::createDateTimeInstance(DateFormat::kShort, DateFormat::kShort, fLocale);
1707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (t->defaultDateFormat == NULL) {
1708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ec = U_MEMORY_ALLOCATION_ERROR;
1709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return defaultDateFormat;
1712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
171485bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoUBool
171585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoMessageFormat::usesNamedArguments() const {
1716b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return msgPattern.hasNamedArguments();
171785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
171885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1720b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessageFormat::getArgTypeCount() const {
1721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return argTypeCount;
1722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool MessageFormat::equalFormats(const void* left, const void* right) {
1725b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return *(const Format*)left==*(const Format*)right;
1726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1727b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1729b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool MessageFormat::DummyFormat::operator==(const Format&) const {
173085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return TRUE;
173185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
173285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoFormat* MessageFormat::DummyFormat::clone() const {
1734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return new DummyFormat();
173527f654740f2a26ad62a5c155af9199af9e69b889claireho}
173685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& MessageFormat::DummyFormat::format(const Formattable&,
1738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                          UnicodeString& appendTo,
173954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                          UErrorCode& status) const {
174054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (U_SUCCESS(status)) {
174154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        status = U_UNSUPPORTED_ERROR;
174254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
174354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return appendTo;
174454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
174554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
174654dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusUnicodeString& MessageFormat::DummyFormat::format(const Formattable&,
174754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                          UnicodeString& appendTo,
1748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                          FieldPosition&,
1749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                          UErrorCode& status) const {
1750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
1751b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_UNSUPPORTED_ERROR;
1752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return appendTo;
1754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
175654dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusUnicodeString& MessageFormat::DummyFormat::format(const Formattable&,
175754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                          UnicodeString& appendTo,
175854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                          FieldPositionIterator*,
175954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius                          UErrorCode& status) const {
176054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    if (U_SUCCESS(status)) {
176154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        status = U_UNSUPPORTED_ERROR;
176254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    }
176354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius    return appendTo;
176454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius}
176554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius
1766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::DummyFormat::parseObject(const UnicodeString&,
1767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                     Formattable&,
1768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                                                     ParsePosition& ) const {
1769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
177285bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoFormatNameEnumeration::FormatNameEnumeration(UVector *fNameList, UErrorCode& /*status*/) {
177385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pos=0;
177485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    fFormatNames = fNameList;
177585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
177685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
177785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoconst UnicodeString*
177885bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoFormatNameEnumeration::snext(UErrorCode& status) {
177985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (U_SUCCESS(status) && pos < fFormatNames->size()) {
178085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return (const UnicodeString*)fFormatNames->elementAt(pos++);
178185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
178285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    return NULL;
178385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
178485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
178585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hovoid
178685bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoFormatNameEnumeration::reset(UErrorCode& /*status*/) {
178785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    pos=0;
178885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
178985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
179085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hoint32_t
179185bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoFormatNameEnumeration::count(UErrorCode& /*status*/) const {
1792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (fFormatNames==NULL) ? 0 : fFormatNames->size();
179385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
179485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
179585bf2e2fbc60a9f938064abc8127d61da7d19882Claire HoFormatNameEnumeration::~FormatNameEnumeration() {
1796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete fFormatNames;
1797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
180054dcd9b6a06071f647dac967e9e267abb9410720Craig CorneliusMessageFormat::PluralSelectorProvider::PluralSelectorProvider(const Locale* loc, UPluralType t)
180154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        : locale(loc), rules(NULL), type(t) {
1802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoMessageFormat::PluralSelectorProvider::~PluralSelectorProvider() {
1805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // We own the rules but not the locale.
1806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete rules;
1807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString MessageFormat::PluralSelectorProvider::select(double number, UErrorCode& ec) const {
1810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
1811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return UnicodeString(FALSE, OTHER_STRING, 5);
1812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MessageFormat::PluralSelectorProvider* t = const_cast<MessageFormat::PluralSelectorProvider*>(this);
1814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(rules == NULL) {
181554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius        t->rules = PluralRules::forLocale(*locale, type, ec);
1816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
1817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return UnicodeString(FALSE, OTHER_STRING, 5);
181885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
181985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
1820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return rules->select(number);
182185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho}
1822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid MessageFormat::PluralSelectorProvider::reset(const Locale* loc) {
1824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    locale = loc;
1825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    delete rules;
1826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    rules = NULL;
1827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
1831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//eof
1835