2 ******************************************************************************
3 * Copyright (C) 2014, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 ******************************************************************************
6 * quantityformatter.cpp
8 #include "quantityformatter.h"
9 #include "simplepatternformatter.h"
11 #include "unicode/unistr.h"
12 #include "unicode/decimfmt.h"
14 #include "plurrule_impl.h"
15 #include "unicode/plurrule.h"
17 #include "unicode/fmtable.h"
18 #include "unicode/fieldpos.h"
20 #if !UCONFIG_NO_FORMATTING
24 // other must always be first.
25 static const char * const gPluralForms
[] = {
26 "other", "zero", "one", "two", "few", "many"};
28 static int32_t getPluralIndex(const char *pluralForm
) {
29 int32_t len
= UPRV_LENGTHOF(gPluralForms
);
30 for (int32_t i
= 0; i
< len
; ++i
) {
31 if (uprv_strcmp(pluralForm
, gPluralForms
[i
]) == 0) {
38 QuantityFormatter::QuantityFormatter() {
39 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
44 QuantityFormatter::QuantityFormatter(const QuantityFormatter
&other
) {
45 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
46 if (other
.formatters
[i
] == NULL
) {
49 formatters
[i
] = new SimplePatternFormatter(*other
.formatters
[i
]);
54 QuantityFormatter
&QuantityFormatter::operator=(
55 const QuantityFormatter
& other
) {
59 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
61 if (other
.formatters
[i
] == NULL
) {
64 formatters
[i
] = new SimplePatternFormatter(*other
.formatters
[i
]);
70 QuantityFormatter::~QuantityFormatter() {
71 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
76 void QuantityFormatter::reset() {
77 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
83 UBool
QuantityFormatter::add(
85 const UnicodeString
&rawPattern
,
87 if (U_FAILURE(status
)) {
90 int32_t pluralIndex
= getPluralIndex(variant
);
91 if (pluralIndex
== -1) {
92 status
= U_ILLEGAL_ARGUMENT_ERROR
;
95 SimplePatternFormatter
*newFmt
=
96 new SimplePatternFormatter(rawPattern
);
98 status
= U_MEMORY_ALLOCATION_ERROR
;
101 if (newFmt
->getPlaceholderCount() > 1) {
103 status
= U_ILLEGAL_ARGUMENT_ERROR
;
106 delete formatters
[pluralIndex
];
107 formatters
[pluralIndex
] = newFmt
;
111 UBool
QuantityFormatter::isValid() const {
112 return formatters
[0] != NULL
;
115 const SimplePatternFormatter
*QuantityFormatter::getByVariant(
116 const char *variant
) const {
117 int32_t pluralIndex
= getPluralIndex(variant
);
118 if (pluralIndex
== -1) {
121 const SimplePatternFormatter
*pattern
= formatters
[pluralIndex
];
122 if (pattern
== NULL
) {
123 pattern
= formatters
[0];
128 UnicodeString
&QuantityFormatter::format(
129 const Formattable
& quantity
,
130 const NumberFormat
&fmt
,
131 const PluralRules
&rules
,
132 UnicodeString
&appendTo
,
134 UErrorCode
&status
) const {
135 if (U_FAILURE(status
)) {
139 const DecimalFormat
*decFmt
= dynamic_cast<const DecimalFormat
*>(&fmt
);
140 if (decFmt
!= NULL
) {
141 FixedDecimal fd
= decFmt
->getFixedDecimal(quantity
, status
);
142 if (U_FAILURE(status
)) {
145 count
= rules
.select(fd
);
147 if (quantity
.getType() == Formattable::kDouble
) {
148 count
= rules
.select(quantity
.getDouble());
149 } else if (quantity
.getType() == Formattable::kLong
) {
150 count
= rules
.select(quantity
.getLong());
151 } else if (quantity
.getType() == Formattable::kInt64
) {
152 count
= rules
.select((double) quantity
.getInt64());
154 status
= U_ILLEGAL_ARGUMENT_ERROR
;
159 buffer
.appendInvariantChars(count
, status
);
160 if (U_FAILURE(status
)) {
163 const SimplePatternFormatter
*pattern
= getByVariant(buffer
.data());
164 if (pattern
== NULL
) {
165 status
= U_INVALID_STATE_ERROR
;
168 UnicodeString formattedNumber
;
169 FieldPosition
fpos(pos
.getField());
170 fmt
.format(quantity
, formattedNumber
, fpos
, status
);
171 const UnicodeString
*params
[1] = {&formattedNumber
};
173 pattern
->formatAndAppend(
175 UPRV_LENGTHOF(params
),
178 UPRV_LENGTHOF(offsets
),
180 if (offsets
[0] != -1) {
181 if (fpos
.getBeginIndex() != 0 || fpos
.getEndIndex() != 0) {
182 pos
.setBeginIndex(fpos
.getBeginIndex() + offsets
[0]);
183 pos
.setEndIndex(fpos
.getEndIndex() + offsets
[0]);
191 #endif /* #if !UCONFIG_NO_FORMATTING */