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