2 ******************************************************************************
3 * Copyright (C) 2014-2016, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 ******************************************************************************
6 * quantityformatter.cpp
9 #include "unicode/utypes.h"
11 #if !UCONFIG_NO_FORMATTING
13 #include "unicode/simpleformatter.h"
14 #include "quantityformatter.h"
16 #include "unicode/unistr.h"
17 #include "unicode/decimfmt.h"
19 #include "unicode/plurrule.h"
21 #include "unicode/fmtable.h"
22 #include "unicode/fieldpos.h"
23 #include "standardplural.h"
24 #include "visibledigits.h"
29 QuantityFormatter::QuantityFormatter() {
30 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
35 QuantityFormatter::QuantityFormatter(const QuantityFormatter
&other
) {
36 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
37 if (other
.formatters
[i
] == NULL
) {
40 formatters
[i
] = new SimpleFormatter(*other
.formatters
[i
]);
45 QuantityFormatter
&QuantityFormatter::operator=(
46 const QuantityFormatter
& other
) {
50 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
52 if (other
.formatters
[i
] == NULL
) {
55 formatters
[i
] = new SimpleFormatter(*other
.formatters
[i
]);
61 QuantityFormatter::~QuantityFormatter() {
62 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
67 void QuantityFormatter::reset() {
68 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
74 UBool
QuantityFormatter::addIfAbsent(
76 const UnicodeString
&rawPattern
,
78 int32_t pluralIndex
= StandardPlural::indexFromString(variant
, status
);
79 if (U_FAILURE(status
)) {
82 if (formatters
[pluralIndex
] != NULL
) {
85 SimpleFormatter
*newFmt
= new SimpleFormatter(rawPattern
, 0, 1, status
);
87 status
= U_MEMORY_ALLOCATION_ERROR
;
90 if (U_FAILURE(status
)) {
94 formatters
[pluralIndex
] = newFmt
;
98 UBool
QuantityFormatter::isValid() const {
99 return formatters
[StandardPlural::OTHER
] != NULL
;
102 const SimpleFormatter
*QuantityFormatter::getByVariant(
103 const char *variant
) const {
105 int32_t pluralIndex
= StandardPlural::indexOrOtherIndexFromString(variant
);
106 const SimpleFormatter
*pattern
= formatters
[pluralIndex
];
107 if (pattern
== NULL
) {
108 pattern
= formatters
[StandardPlural::OTHER
];
113 UnicodeString
&QuantityFormatter::format(
114 const Formattable
&number
,
115 const NumberFormat
&fmt
,
116 const PluralRules
&rules
,
117 UnicodeString
&appendTo
,
119 UErrorCode
&status
) const {
120 UnicodeString formattedNumber
;
121 StandardPlural::Form p
= selectPlural(number
, fmt
, rules
, formattedNumber
, pos
, status
);
122 if (U_FAILURE(status
)) {
125 const SimpleFormatter
*pattern
= formatters
[p
];
126 if (pattern
== NULL
) {
127 pattern
= formatters
[StandardPlural::OTHER
];
128 if (pattern
== NULL
) {
129 status
= U_INVALID_STATE_ERROR
;
133 return format(*pattern
, formattedNumber
, appendTo
, pos
, status
);
136 // The following methods live here so that class PluralRules does not depend on number formatting,
137 // and the SimpleFormatter does not depend on FieldPosition.
139 StandardPlural::Form
QuantityFormatter::selectPlural(
140 const Formattable
&number
,
141 const NumberFormat
&fmt
,
142 const PluralRules
&rules
,
143 UnicodeString
&formattedNumber
,
145 UErrorCode
&status
) {
146 if (U_FAILURE(status
)) {
147 return StandardPlural::OTHER
;
149 UnicodeString pluralKeyword
;
150 VisibleDigitsWithExponent digits
;
151 const DecimalFormat
*decFmt
= dynamic_cast<const DecimalFormat
*>(&fmt
);
152 if (decFmt
!= NULL
) {
153 decFmt
->initVisibleDigitsWithExponent(number
, digits
, status
);
154 if (U_FAILURE(status
)) {
155 return StandardPlural::OTHER
;
157 pluralKeyword
= rules
.select(digits
);
158 decFmt
->format(digits
, formattedNumber
, pos
, status
);
160 if (number
.getType() == Formattable::kDouble
) {
161 pluralKeyword
= rules
.select(number
.getDouble());
162 } else if (number
.getType() == Formattable::kLong
) {
163 pluralKeyword
= rules
.select(number
.getLong());
164 } else if (number
.getType() == Formattable::kInt64
) {
165 pluralKeyword
= rules
.select((double) number
.getInt64());
167 status
= U_ILLEGAL_ARGUMENT_ERROR
;
168 return StandardPlural::OTHER
;
170 fmt
.format(number
, formattedNumber
, pos
, status
);
172 return StandardPlural::orOtherFromString(pluralKeyword
);
175 UnicodeString
&QuantityFormatter::format(
176 const SimpleFormatter
&pattern
,
177 const UnicodeString
&value
,
178 UnicodeString
&appendTo
,
180 UErrorCode
&status
) {
181 if (U_FAILURE(status
)) {
184 const UnicodeString
*param
= &value
;
186 pattern
.formatAndAppend(¶m
, 1, appendTo
, &offset
, 1, status
);
187 if (pos
.getBeginIndex() != 0 || pos
.getEndIndex() != 0) {
189 pos
.setBeginIndex(pos
.getBeginIndex() + offset
);
190 pos
.setEndIndex(pos
.getEndIndex() + offset
);
192 pos
.setBeginIndex(0);
201 #endif /* #if !UCONFIG_NO_FORMATTING */