• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ******************************************************************************
3 * Copyright (C) 2014-2015, International Business Machines
4 * Corporation and others.  All Rights Reserved.
5 ******************************************************************************
6 * quantityformatter.cpp
7 */
8 
9 #include "unicode/utypes.h"
10 
11 #if !UCONFIG_NO_FORMATTING
12 
13 #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"
19 #include "unicode/plurrule.h"
20 #include "charstr.h"
21 #include "unicode/fmtable.h"
22 #include "unicode/fieldpos.h"
23 #include "standardplural.h"
24 #include "visibledigits.h"
25 #include "uassert.h"
26 
27 U_NAMESPACE_BEGIN
28 
QuantityFormatter()29 QuantityFormatter::QuantityFormatter() {
30     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
31         formatters[i] = NULL;
32     }
33 }
34 
QuantityFormatter(const QuantityFormatter & other)35 QuantityFormatter::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 
operator =(const QuantityFormatter & other)45 QuantityFormatter &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 
~QuantityFormatter()61 QuantityFormatter::~QuantityFormatter() {
62     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
63         delete formatters[i];
64     }
65 }
66 
reset()67 void QuantityFormatter::reset() {
68     for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
69         delete formatters[i];
70         formatters[i] = NULL;
71     }
72 }
73 
addIfAbsent(const char * variant,const UnicodeString & rawPattern,UErrorCode & status)74 UBool QuantityFormatter::addIfAbsent(
75         const char *variant,
76         const UnicodeString &rawPattern,
77         UErrorCode &status) {
78     int32_t pluralIndex = StandardPlural::indexFromString(variant, status);
79     if (U_FAILURE(status)) {
80         return FALSE;
81     }
82     if (formatters[pluralIndex] != NULL) {
83         return TRUE;
84     }
85     SimplePatternFormatter *newFmt = new SimplePatternFormatter(rawPattern, 0, 1, status);
86     if (newFmt == NULL) {
87         status = U_MEMORY_ALLOCATION_ERROR;
88         return FALSE;
89     }
90     if (U_FAILURE(status)) {
91         delete newFmt;
92         return FALSE;
93     }
94     formatters[pluralIndex] = newFmt;
95     return TRUE;
96 }
97 
isValid() const98 UBool QuantityFormatter::isValid() const {
99     return formatters[StandardPlural::OTHER] != NULL;
100 }
101 
getByVariant(const char * variant) const102 const SimplePatternFormatter *QuantityFormatter::getByVariant(
103         const char *variant) const {
104     U_ASSERT(isValid());
105     int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant);
106     const SimplePatternFormatter *pattern = formatters[pluralIndex];
107     if (pattern == NULL) {
108         pattern = formatters[StandardPlural::OTHER];
109     }
110     return pattern;
111 }
112 
format(const Formattable & number,const NumberFormat & fmt,const PluralRules & rules,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status) const113 UnicodeString &QuantityFormatter::format(
114             const Formattable &number,
115             const NumberFormat &fmt,
116             const PluralRules &rules,
117             UnicodeString &appendTo,
118             FieldPosition &pos,
119             UErrorCode &status) const {
120     UnicodeString formattedNumber;
121     StandardPlural::Form p = selectPlural(number, fmt, rules, formattedNumber, pos, status);
122     if (U_FAILURE(status)) {
123         return appendTo;
124     }
125     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 
selectPlural(const Formattable & number,const NumberFormat & fmt,const PluralRules & rules,UnicodeString & formattedNumber,FieldPosition & pos,UErrorCode & status)139 StandardPlural::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;
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;
156         }
157         pluralKeyword = rules.select(digits);
158         decFmt->format(digits, formattedNumber, pos, status);
159     } else {
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());
166         } else {
167             status = U_ILLEGAL_ARGUMENT_ERROR;
168             return StandardPlural::OTHER;
169         }
170         fmt.format(number, formattedNumber, pos, status);
171     }
172     return StandardPlural::orOtherFromString(pluralKeyword);
173 }
174 
format(const SimplePatternFormatter & pattern,const UnicodeString & value,UnicodeString & appendTo,FieldPosition & pos,UErrorCode & status)175 UnicodeString &QuantityFormatter::format(
176             const SimplePatternFormatter &pattern,
177             const UnicodeString &value,
178             UnicodeString &appendTo,
179             FieldPosition &pos,
180             UErrorCode &status) {
181     if (U_FAILURE(status)) {
182         return appendTo;
183     }
184     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);
194         }
195     }
196     return appendTo;
197 }
198 
199 U_NAMESPACE_END
200 
201 #endif /* #if !UCONFIG_NO_FORMATTING */
202