Coverage Report

Created: 2018-09-25 14:53

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