1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
5 * Copyright (C) 2014-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 ******************************************************************************
8 * quantityformatter.cpp
11 #include "unicode/utypes.h"
13 #if !UCONFIG_NO_FORMATTING
15 #include "unicode/simpleformatter.h"
16 #include "quantityformatter.h"
18 #include "unicode/unistr.h"
19 #include "unicode/decimfmt.h"
21 #include "unicode/plurrule.h"
23 #include "unicode/fmtable.h"
24 #include "unicode/fieldpos.h"
25 #include "standardplural.h"
26 #include "visibledigits.h"
31 QuantityFormatter::QuantityFormatter() {
32 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
37 QuantityFormatter::QuantityFormatter(const QuantityFormatter
&other
) {
38 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
39 if (other
.formatters
[i
] == NULL
) {
42 formatters
[i
] = new SimpleFormatter(*other
.formatters
[i
]);
47 QuantityFormatter
&QuantityFormatter::operator=(
48 const QuantityFormatter
& other
) {
52 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
54 if (other
.formatters
[i
] == NULL
) {
57 formatters
[i
] = new SimpleFormatter(*other
.formatters
[i
]);
63 QuantityFormatter::~QuantityFormatter() {
64 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
69 void QuantityFormatter::reset() {
70 for (int32_t i
= 0; i
< UPRV_LENGTHOF(formatters
); ++i
) {
76 UBool
QuantityFormatter::addIfAbsent(
78 const UnicodeString
&rawPattern
,
80 int32_t pluralIndex
= StandardPlural::indexFromString(variant
, status
);
81 if (U_FAILURE(status
)) {
84 if (formatters
[pluralIndex
] != NULL
) {
87 SimpleFormatter
*newFmt
= new SimpleFormatter(rawPattern
, 0, 1, status
);
89 status
= U_MEMORY_ALLOCATION_ERROR
;
92 if (U_FAILURE(status
)) {
96 formatters
[pluralIndex
] = newFmt
;
100 UBool
QuantityFormatter::isValid() const {
101 return formatters
[StandardPlural::OTHER
] != NULL
;
104 const SimpleFormatter
*QuantityFormatter::getByVariant(
105 const char *variant
) const {
107 int32_t pluralIndex
= StandardPlural::indexOrOtherIndexFromString(variant
);
108 const SimpleFormatter
*pattern
= formatters
[pluralIndex
];
109 if (pattern
== NULL
) {
110 pattern
= formatters
[StandardPlural::OTHER
];
115 UnicodeString
&QuantityFormatter::format(
116 const Formattable
&number
,
117 const NumberFormat
&fmt
,
118 const PluralRules
&rules
,
119 UnicodeString
&appendTo
,
121 UErrorCode
&status
) const {
122 UnicodeString formattedNumber
;
123 StandardPlural::Form p
= selectPlural(number
, fmt
, rules
, formattedNumber
, pos
, status
);
124 if (U_FAILURE(status
)) {
127 const SimpleFormatter
*pattern
= formatters
[p
];
128 if (pattern
== NULL
) {
129 pattern
= formatters
[StandardPlural::OTHER
];
130 if (pattern
== NULL
) {
131 status
= U_INVALID_STATE_ERROR
;
135 return format(*pattern
, formattedNumber
, appendTo
, pos
, status
);
138 // The following methods live here so that class PluralRules does not depend on number formatting,
139 // and the SimpleFormatter does not depend on FieldPosition.
141 StandardPlural::Form
QuantityFormatter::selectPlural(
142 const Formattable
&number
,
143 const NumberFormat
&fmt
,
144 const PluralRules
&rules
,
145 UnicodeString
&formattedNumber
,
147 UErrorCode
&status
) {
148 if (U_FAILURE(status
)) {
149 return StandardPlural::OTHER
;
151 UnicodeString pluralKeyword
;
152 VisibleDigitsWithExponent digits
;
153 const DecimalFormat
*decFmt
= dynamic_cast<const DecimalFormat
*>(&fmt
);
154 if (decFmt
!= NULL
) {
155 decFmt
->initVisibleDigitsWithExponent(number
, digits
, status
);
156 if (U_FAILURE(status
)) {
157 return StandardPlural::OTHER
;
159 pluralKeyword
= rules
.select(digits
);
160 decFmt
->format(digits
, formattedNumber
, pos
, status
);
162 if (number
.getType() == Formattable::kDouble
) {
163 pluralKeyword
= rules
.select(number
.getDouble());
164 } else if (number
.getType() == Formattable::kLong
) {
165 pluralKeyword
= rules
.select(number
.getLong());
166 } else if (number
.getType() == Formattable::kInt64
) {
167 pluralKeyword
= rules
.select((double) number
.getInt64());
169 status
= U_ILLEGAL_ARGUMENT_ERROR
;
170 return StandardPlural::OTHER
;
172 fmt
.format(number
, formattedNumber
, pos
, status
);
174 return StandardPlural::orOtherFromString(pluralKeyword
);
177 UnicodeString
&QuantityFormatter::format(
178 const SimpleFormatter
&pattern
,
179 const UnicodeString
&value
,
180 UnicodeString
&appendTo
,
182 UErrorCode
&status
) {
183 if (U_FAILURE(status
)) {
186 const UnicodeString
*param
= &value
;
188 pattern
.formatAndAppend(¶m
, 1, appendTo
, &offset
, 1, status
);
189 if (pos
.getBeginIndex() != 0 || pos
.getEndIndex() != 0) {
191 pos
.setBeginIndex(pos
.getBeginIndex() + offset
);
192 pos
.setEndIndex(pos
.getEndIndex() + offset
);
194 pos
.setBeginIndex(0);
203 #endif /* #if !UCONFIG_NO_FORMATTING */