blob: ba06ba06b97013bec98988549804907be3809f1e [file] [log] [blame]
Jungshik Shin87232d82017-05-13 21:10:13 -07001// © 2016 and later: Unicode, Inc. and others.
Jungshik Shin5feb9ad2016-10-21 12:52:48 -07002// License & terms of use: http://www.unicode.org/copyright.html
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -08003/*
4******************************************************************************
Jungshik Shin5feb9ad2016-10-21 12:52:48 -07005* Copyright (C) 2014-2016, International Business Machines
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -08006* Corporation and others. All Rights Reserved.
7******************************************************************************
8* quantityformatter.cpp
9*/
Jungshik Shin825221b2016-01-29 01:05:51 -080010
11#include "unicode/utypes.h"
12
13#if !UCONFIG_NO_FORMATTING
14
Jungshik Shin5feb9ad2016-10-21 12:52:48 -070015#include "unicode/simpleformatter.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080016#include "quantityformatter.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080017#include "uassert.h"
18#include "unicode/unistr.h"
19#include "unicode/decimfmt.h"
20#include "cstring.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080021#include "unicode/plurrule.h"
22#include "charstr.h"
23#include "unicode/fmtable.h"
24#include "unicode/fieldpos.h"
Jungshik Shin825221b2016-01-29 01:05:51 -080025#include "standardplural.h"
Jungshik Shin825221b2016-01-29 01:05:51 -080026#include "uassert.h"
Jungshik Shina9a2bd32018-07-07 03:36:01 -070027#include "number_decimalquantity.h"
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080028
29U_NAMESPACE_BEGIN
30
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080031QuantityFormatter::QuantityFormatter() {
32 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
33 formatters[i] = NULL;
34 }
35}
36
37QuantityFormatter::QuantityFormatter(const QuantityFormatter &other) {
38 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
39 if (other.formatters[i] == NULL) {
40 formatters[i] = NULL;
41 } else {
Jungshik Shin5feb9ad2016-10-21 12:52:48 -070042 formatters[i] = new SimpleFormatter(*other.formatters[i]);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080043 }
44 }
45}
46
47QuantityFormatter &QuantityFormatter::operator=(
48 const QuantityFormatter& other) {
49 if (this == &other) {
50 return *this;
51 }
52 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
53 delete formatters[i];
54 if (other.formatters[i] == NULL) {
55 formatters[i] = NULL;
56 } else {
Jungshik Shin5feb9ad2016-10-21 12:52:48 -070057 formatters[i] = new SimpleFormatter(*other.formatters[i]);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080058 }
59 }
60 return *this;
61}
62
63QuantityFormatter::~QuantityFormatter() {
64 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
65 delete formatters[i];
66 }
67}
68
69void QuantityFormatter::reset() {
70 for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
71 delete formatters[i];
72 formatters[i] = NULL;
73 }
74}
75
Jungshik Shin825221b2016-01-29 01:05:51 -080076UBool QuantityFormatter::addIfAbsent(
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080077 const char *variant,
78 const UnicodeString &rawPattern,
79 UErrorCode &status) {
Jungshik Shin825221b2016-01-29 01:05:51 -080080 int32_t pluralIndex = StandardPlural::indexFromString(variant, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080081 if (U_FAILURE(status)) {
82 return FALSE;
83 }
Jungshik Shin825221b2016-01-29 01:05:51 -080084 if (formatters[pluralIndex] != NULL) {
85 return TRUE;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080086 }
Jungshik Shin5feb9ad2016-10-21 12:52:48 -070087 SimpleFormatter *newFmt = new SimpleFormatter(rawPattern, 0, 1, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080088 if (newFmt == NULL) {
89 status = U_MEMORY_ALLOCATION_ERROR;
90 return FALSE;
91 }
Jungshik Shin825221b2016-01-29 01:05:51 -080092 if (U_FAILURE(status)) {
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080093 delete newFmt;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080094 return FALSE;
95 }
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -080096 formatters[pluralIndex] = newFmt;
97 return TRUE;
98}
99
100UBool QuantityFormatter::isValid() const {
Jungshik Shin825221b2016-01-29 01:05:51 -0800101 return formatters[StandardPlural::OTHER] != NULL;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800102}
103
Jungshik Shin5feb9ad2016-10-21 12:52:48 -0700104const SimpleFormatter *QuantityFormatter::getByVariant(
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800105 const char *variant) const {
Jungshik Shin825221b2016-01-29 01:05:51 -0800106 U_ASSERT(isValid());
107 int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant);
Jungshik Shin5feb9ad2016-10-21 12:52:48 -0700108 const SimpleFormatter *pattern = formatters[pluralIndex];
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800109 if (pattern == NULL) {
Jungshik Shin825221b2016-01-29 01:05:51 -0800110 pattern = formatters[StandardPlural::OTHER];
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800111 }
112 return pattern;
113}
114
115UnicodeString &QuantityFormatter::format(
Jungshik Shin825221b2016-01-29 01:05:51 -0800116 const Formattable &number,
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800117 const NumberFormat &fmt,
118 const PluralRules &rules,
119 UnicodeString &appendTo,
120 FieldPosition &pos,
121 UErrorCode &status) const {
Jungshik Shin825221b2016-01-29 01:05:51 -0800122 UnicodeString formattedNumber;
123 StandardPlural::Form p = selectPlural(number, fmt, rules, formattedNumber, pos, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800124 if (U_FAILURE(status)) {
125 return appendTo;
126 }
Jungshik Shin5feb9ad2016-10-21 12:52:48 -0700127 const SimpleFormatter *pattern = formatters[p];
Jungshik Shin825221b2016-01-29 01:05:51 -0800128 if (pattern == NULL) {
129 pattern = formatters[StandardPlural::OTHER];
130 if (pattern == NULL) {
131 status = U_INVALID_STATE_ERROR;
132 return appendTo;
133 }
134 }
135 return format(*pattern, formattedNumber, appendTo, pos, status);
136}
137
138// The following methods live here so that class PluralRules does not depend on number formatting,
Jungshik Shin5feb9ad2016-10-21 12:52:48 -0700139// and the SimpleFormatter does not depend on FieldPosition.
Jungshik Shin825221b2016-01-29 01:05:51 -0800140
141StandardPlural::Form QuantityFormatter::selectPlural(
142 const Formattable &number,
143 const NumberFormat &fmt,
144 const PluralRules &rules,
145 UnicodeString &formattedNumber,
146 FieldPosition &pos,
147 UErrorCode &status) {
148 if (U_FAILURE(status)) {
149 return StandardPlural::OTHER;
150 }
151 UnicodeString pluralKeyword;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800152 const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
153 if (decFmt != NULL) {
Jungshik Shina9a2bd32018-07-07 03:36:01 -0700154 number::impl::DecimalQuantity dq;
155 decFmt->formatToDecimalQuantity(number, dq, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800156 if (U_FAILURE(status)) {
Jungshik Shin825221b2016-01-29 01:05:51 -0800157 return StandardPlural::OTHER;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800158 }
Jungshik Shina9a2bd32018-07-07 03:36:01 -0700159 pluralKeyword = rules.select(dq);
160 decFmt->format(number, formattedNumber, pos, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800161 } else {
Jungshik Shin825221b2016-01-29 01:05:51 -0800162 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());
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800168 } else {
169 status = U_ILLEGAL_ARGUMENT_ERROR;
Jungshik Shin825221b2016-01-29 01:05:51 -0800170 return StandardPlural::OTHER;
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800171 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800172 fmt.format(number, formattedNumber, pos, status);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800173 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800174 return StandardPlural::orOtherFromString(pluralKeyword);
175}
176
177UnicodeString &QuantityFormatter::format(
Jungshik Shin5feb9ad2016-10-21 12:52:48 -0700178 const SimpleFormatter &pattern,
Jungshik Shin825221b2016-01-29 01:05:51 -0800179 const UnicodeString &value,
180 UnicodeString &appendTo,
181 FieldPosition &pos,
182 UErrorCode &status) {
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800183 if (U_FAILURE(status)) {
184 return appendTo;
185 }
Jungshik Shin825221b2016-01-29 01:05:51 -0800186 const UnicodeString *param = &value;
187 int32_t offset;
188 pattern.formatAndAppend(&param, 1, appendTo, &offset, 1, status);
189 if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) {
190 if (offset >= 0) {
191 pos.setBeginIndex(pos.getBeginIndex() + offset);
192 pos.setEndIndex(pos.getEndIndex() + offset);
193 } else {
194 pos.setBeginIndex(0);
195 pos.setEndIndex(0);
Jungshik Shin (jungshik at google)0f8746a2015-01-08 15:46:45 -0800196 }
197 }
198 return appendTo;
199}
200
201U_NAMESPACE_END
202
203#endif /* #if !UCONFIG_NO_FORMATTING */