blob: 97c4c80fa82620f23d6974cccf3cbcf220ad7724 [file] [log] [blame]
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -08001/*
2******************************************************************************
Jungshik Shin70f82502016-01-29 00:32:36 -08003* Copyright (C) 2014-2015, International Business Machines
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -08004* Corporation and others. All Rights Reserved.
5******************************************************************************
6* quantityformatter.cpp
7*/
Jungshik Shin825221b2016-01-29 01:05:51 -08008
9#include "unicode/utypes.h"
10
11#if !UCONFIG_NO_FORMATTING
12
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080013#include "quantityformatter.h"
14#include "simplepatternformatter.h"
15#include "uassert.h"
16#include "unicode/unistr.h"
17#include "unicode/decimfmt.h"
18#include "cstring.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080019#include "unicode/plurrule.h"
20#include "charstr.h"
21#include "unicode/fmtable.h"
22#include "unicode/fieldpos.h"
Jungshik Shin825221b2016-01-29 01:05:51 -080023#include "standardplural.h"
Jungshik Shin70f82502016-01-29 00:32:36 -080024#include "visibledigits.h"
Jungshik Shin825221b2016-01-29 01:05:51 -080025#include "uassert.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080026
27U_NAMESPACE_BEGIN
28
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080029QuantityFormatter::QuantityFormatter() {
30 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
31 formatters[i] = NULL;
32 }
33}
34
35QuantityFormatter::QuantityFormatter(const QuantityFormatter &other) {
36 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
37 if (other.formatters[i] == NULL) {
38 formatters[i] = NULL;
39 } else {
40 formatters[i] = new SimplePatternFormatter(*other.formatters[i]);
41 }
42 }
43}
44
45QuantityFormatter &QuantityFormatter::operator=(
46 const QuantityFormatter& other) {
47 if (this == &other) {
48 return *this;
49 }
50 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
51 delete formatters[i];
52 if (other.formatters[i] == NULL) {
53 formatters[i] = NULL;
54 } else {
55 formatters[i] = new SimplePatternFormatter(*other.formatters[i]);
56 }
57 }
58 return *this;
59}
60
61QuantityFormatter::~QuantityFormatter() {
62 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
63 delete formatters[i];
64 }
65}
66
67void QuantityFormatter::reset() {
68 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
69 delete formatters[i];
70 formatters[i] = NULL;
71 }
72}
73
Jungshik Shin825221b2016-01-29 01:05:51 -080074UBool QuantityFormatter::addIfAbsent(
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080075 const char *variant,
76 const UnicodeString &rawPattern,
77 UErrorCode &status) {
Jungshik Shin825221b2016-01-29 01:05:51 -080078 int32_t pluralIndex = StandardPlural::indexFromString(variant, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080079 if (U_FAILURE(status)) {
80 return FALSE;
81 }
Jungshik Shin825221b2016-01-29 01:05:51 -080082 if (formatters[pluralIndex] != NULL) {
83 return TRUE;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080084 }
Jungshik Shin825221b2016-01-29 01:05:51 -080085 SimplePatternFormatter *newFmt = new SimplePatternFormatter(rawPattern, 0, 1, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080086 if (newFmt == NULL) {
87 status = U_MEMORY_ALLOCATION_ERROR;
88 return FALSE;
89 }
Jungshik Shin825221b2016-01-29 01:05:51 -080090 if (U_FAILURE(status)) {
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080091 delete newFmt;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080092 return FALSE;
93 }
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080094 formatters[pluralIndex] = newFmt;
95 return TRUE;
96}
97
98UBool QuantityFormatter::isValid() const {
Jungshik Shin825221b2016-01-29 01:05:51 -080099 return formatters[StandardPlural::OTHER] != NULL;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800100}
101
102const SimplePatternFormatter *QuantityFormatter::getByVariant(
103 const char *variant) const {
Jungshik Shin825221b2016-01-29 01:05:51 -0800104 U_ASSERT(isValid());
105 int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800106 const SimplePatternFormatter *pattern = formatters[pluralIndex];
107 if (pattern == NULL) {
Jungshik Shin825221b2016-01-29 01:05:51 -0800108 pattern = formatters[StandardPlural::OTHER];
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800109 }
110 return pattern;
111}
112
113UnicodeString &QuantityFormatter::format(
Jungshik Shin825221b2016-01-29 01:05:51 -0800114 const Formattable &number,
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800115 const NumberFormat &fmt,
116 const PluralRules &rules,
117 UnicodeString &appendTo,
118 FieldPosition &pos,
119 UErrorCode &status) const {
Jungshik Shin825221b2016-01-29 01:05:51 -0800120 UnicodeString formattedNumber;
121 StandardPlural::Form p = selectPlural(number, fmt, rules, formattedNumber, pos, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800122 if (U_FAILURE(status)) {
123 return appendTo;
124 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800125 const SimplePatternFormatter *pattern = formatters[p];
126 if (pattern == NULL) {
127 pattern = formatters[StandardPlural::OTHER];
128 if (pattern == NULL) {
129 status = U_INVALID_STATE_ERROR;
130 return appendTo;
131 }
132 }
133 return format(*pattern, formattedNumber, appendTo, pos, status);
134}
135
136// The following methods live here so that class PluralRules does not depend on number formatting,
137// and the SimplePatternFormatter does not depend on FieldPosition.
138
139StandardPlural::Form QuantityFormatter::selectPlural(
140 const Formattable &number,
141 const NumberFormat &fmt,
142 const PluralRules &rules,
143 UnicodeString &formattedNumber,
144 FieldPosition &pos,
145 UErrorCode &status) {
146 if (U_FAILURE(status)) {
147 return StandardPlural::OTHER;
148 }
149 UnicodeString pluralKeyword;
Jungshik Shin70f82502016-01-29 00:32:36 -0800150 VisibleDigitsWithExponent digits;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800151 const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
152 if (decFmt != NULL) {
Jungshik Shin825221b2016-01-29 01:05:51 -0800153 decFmt->initVisibleDigitsWithExponent(number, digits, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800154 if (U_FAILURE(status)) {
Jungshik Shin825221b2016-01-29 01:05:51 -0800155 return StandardPlural::OTHER;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800156 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800157 pluralKeyword = rules.select(digits);
158 decFmt->format(digits, formattedNumber, pos, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800159 } else {
Jungshik Shin825221b2016-01-29 01:05:51 -0800160 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());
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800166 } else {
167 status = U_ILLEGAL_ARGUMENT_ERROR;
Jungshik Shin825221b2016-01-29 01:05:51 -0800168 return StandardPlural::OTHER;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800169 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800170 fmt.format(number, formattedNumber, pos, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800171 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800172 return StandardPlural::orOtherFromString(pluralKeyword);
173}
174
175UnicodeString &QuantityFormatter::format(
176 const SimplePatternFormatter &pattern,
177 const UnicodeString &value,
178 UnicodeString &appendTo,
179 FieldPosition &pos,
180 UErrorCode &status) {
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800181 if (U_FAILURE(status)) {
182 return appendTo;
183 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800184 const UnicodeString *param = &value;
185 int32_t offset;
186 pattern.formatAndAppend(&param, 1, appendTo, &offset, 1, status);
187 if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) {
188 if (offset >= 0) {
189 pos.setBeginIndex(pos.getBeginIndex() + offset);
190 pos.setEndIndex(pos.getEndIndex() + offset);
191 } else {
192 pos.setBeginIndex(0);
193 pos.setEndIndex(0);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800194 }
195 }
196 return appendTo;
197}
198
199U_NAMESPACE_END
200
201#endif /* #if !UCONFIG_NO_FORMATTING */