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 #define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))
22 #if !UCONFIG_NO_FORMATTING
26 // other must always be first.
27 static const char * const gPluralForms
[] = {
28 "other", "zero", "one", "two", "few", "many"};
30 static int32_t getPluralIndex(const char *pluralForm
) {
31 int32_t len
= LENGTHOF(gPluralForms
);
32 for (int32_t i
= 0; i
< len
; ++i
) {
33 if (uprv_strcmp(pluralForm
, gPluralForms
[i
]) == 0) {
40 QuantityFormatter::QuantityFormatter() {
41 for (int32_t i
= 0; i
< LENGTHOF(formatters
); ++i
) {
46 QuantityFormatter::QuantityFormatter(const QuantityFormatter
&other
) {
47 for (int32_t i
= 0; i
< LENGTHOF(formatters
); ++i
) {
48 if (other
.formatters
[i
] == NULL
) {
51 formatters
[i
] = new SimplePatternFormatter(*other
.formatters
[i
]);
56 QuantityFormatter
&QuantityFormatter::operator=(
57 const QuantityFormatter
& other
) {
61 for (int32_t i
= 0; i
< LENGTHOF(formatters
); ++i
) {
63 if (other
.formatters
[i
] == NULL
) {
66 formatters
[i
] = new SimplePatternFormatter(*other
.formatters
[i
]);
72 QuantityFormatter::~QuantityFormatter() {
73 for (int32_t i
= 0; i
< LENGTHOF(formatters
); ++i
) {
78 void QuantityFormatter::reset() {
79 for (int32_t i
= 0; i
< LENGTHOF(formatters
); ++i
) {
85 UBool
QuantityFormatter::add(
87 const UnicodeString
&rawPattern
,
89 if (U_FAILURE(status
)) {
92 int32_t pluralIndex
= getPluralIndex(variant
);
93 if (pluralIndex
== -1) {
94 status
= U_ILLEGAL_ARGUMENT_ERROR
;
97 SimplePatternFormatter
*newFmt
=
98 new SimplePatternFormatter(rawPattern
);
100 status
= U_MEMORY_ALLOCATION_ERROR
;
103 if (newFmt
->getPlaceholderCount() > 1) {
105 status
= U_ILLEGAL_ARGUMENT_ERROR
;
108 delete formatters
[pluralIndex
];
109 formatters
[pluralIndex
] = newFmt
;
113 UBool
QuantityFormatter::isValid() const {
114 return formatters
[0] != NULL
;
117 UnicodeString
&QuantityFormatter::format(
118 const Formattable
& quantity
,
119 const NumberFormat
&fmt
,
120 const PluralRules
&rules
,
121 UnicodeString
&appendTo
,
123 UErrorCode
&status
) const {
124 if (U_FAILURE(status
)) {
128 const DecimalFormat
*decFmt
= dynamic_cast<const DecimalFormat
*>(&fmt
);
129 if (decFmt
!= NULL
) {
130 FixedDecimal fd
= decFmt
->getFixedDecimal(quantity
, status
);
131 if (U_FAILURE(status
)) {
134 count
= rules
.select(fd
);
136 if (quantity
.getType() == Formattable::kDouble
) {
137 count
= rules
.select(quantity
.getDouble());
138 } else if (quantity
.getType() == Formattable::kLong
) {
139 count
= rules
.select(quantity
.getLong());
140 } else if (quantity
.getType() == Formattable::kInt64
) {
141 count
= rules
.select((double) quantity
.getInt64());
143 status
= U_ILLEGAL_ARGUMENT_ERROR
;
148 buffer
.appendInvariantChars(count
, status
);
149 if (U_FAILURE(status
)) {
152 int32_t pluralIndex
= getPluralIndex(buffer
.data());
153 if (pluralIndex
== -1) {
156 const SimplePatternFormatter
*pattern
= formatters
[pluralIndex
];
157 if (pattern
== NULL
) {
158 pattern
= formatters
[0];
160 if (pattern
== NULL
) {
161 status
= U_INVALID_STATE_ERROR
;
164 UnicodeString formattedNumber
;
165 FieldPosition
fpos(pos
.getField());
166 fmt
.format(quantity
, formattedNumber
, fpos
, status
);
167 const UnicodeString
*params
[1] = {&formattedNumber
};
169 pattern
->format(params
, LENGTHOF(params
), appendTo
, offsets
, LENGTHOF(offsets
), status
);
170 if (offsets
[0] != -1) {
171 if (fpos
.getBeginIndex() != 0 || fpos
.getEndIndex() != 0) {
172 pos
.setBeginIndex(fpos
.getBeginIndex() + offsets
[0]);
173 pos
.setEndIndex(fpos
.getEndIndex() + offsets
[0]);
181 #endif /* #if !UCONFIG_NO_FORMATTING */