]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/quantityformatter.cpp
ICU-531.31.tar.gz
[apple/icu.git] / icuSources / i18n / quantityformatter.cpp
CommitLineData
57a6839d
A
1/*
2******************************************************************************
3* Copyright (C) 2014, International Business Machines
4* Corporation and others. All Rights Reserved.
5******************************************************************************
6* quantityformatter.cpp
7*/
8#include "quantityformatter.h"
9#include "simplepatternformatter.h"
10#include "uassert.h"
11#include "unicode/unistr.h"
12#include "unicode/decimfmt.h"
13#include "cstring.h"
14#include "plurrule_impl.h"
15#include "unicode/plurrule.h"
16#include "charstr.h"
17#include "unicode/fmtable.h"
18#include "unicode/fieldpos.h"
19
20#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))
21
22#if !UCONFIG_NO_FORMATTING
23
24U_NAMESPACE_BEGIN
25
26// other must always be first.
27static const char * const gPluralForms[] = {
28 "other", "zero", "one", "two", "few", "many"};
29
30static int32_t getPluralIndex(const char *pluralForm) {
31 int32_t len = LENGTHOF(gPluralForms);
32 for (int32_t i = 0; i < len; ++i) {
33 if (uprv_strcmp(pluralForm, gPluralForms[i]) == 0) {
34 return i;
35 }
36 }
37 return -1;
38}
39
40QuantityFormatter::QuantityFormatter() {
41 for (int32_t i = 0; i < LENGTHOF(formatters); ++i) {
42 formatters[i] = NULL;
43 }
44}
45
46QuantityFormatter::QuantityFormatter(const QuantityFormatter &other) {
47 for (int32_t i = 0; i < LENGTHOF(formatters); ++i) {
48 if (other.formatters[i] == NULL) {
49 formatters[i] = NULL;
50 } else {
51 formatters[i] = new SimplePatternFormatter(*other.formatters[i]);
52 }
53 }
54}
55
56QuantityFormatter &QuantityFormatter::operator=(
57 const QuantityFormatter& other) {
58 if (this == &other) {
59 return *this;
60 }
61 for (int32_t i = 0; i < LENGTHOF(formatters); ++i) {
62 delete formatters[i];
63 if (other.formatters[i] == NULL) {
64 formatters[i] = NULL;
65 } else {
66 formatters[i] = new SimplePatternFormatter(*other.formatters[i]);
67 }
68 }
69 return *this;
70}
71
72QuantityFormatter::~QuantityFormatter() {
73 for (int32_t i = 0; i < LENGTHOF(formatters); ++i) {
74 delete formatters[i];
75 }
76}
77
78void QuantityFormatter::reset() {
79 for (int32_t i = 0; i < LENGTHOF(formatters); ++i) {
80 delete formatters[i];
81 formatters[i] = NULL;
82 }
83}
84
85UBool QuantityFormatter::add(
86 const char *variant,
87 const UnicodeString &rawPattern,
88 UErrorCode &status) {
89 if (U_FAILURE(status)) {
90 return FALSE;
91 }
92 int32_t pluralIndex = getPluralIndex(variant);
93 if (pluralIndex == -1) {
94 status = U_ILLEGAL_ARGUMENT_ERROR;
95 return FALSE;
96 }
97 SimplePatternFormatter *newFmt =
98 new SimplePatternFormatter(rawPattern);
99 if (newFmt == NULL) {
100 status = U_MEMORY_ALLOCATION_ERROR;
101 return FALSE;
102 }
103 if (newFmt->getPlaceholderCount() > 1) {
104 delete newFmt;
105 status = U_ILLEGAL_ARGUMENT_ERROR;
106 return FALSE;
107 }
108 delete formatters[pluralIndex];
109 formatters[pluralIndex] = newFmt;
110 return TRUE;
111}
112
113UBool QuantityFormatter::isValid() const {
114 return formatters[0] != NULL;
115}
116
117UnicodeString &QuantityFormatter::format(
118 const Formattable& quantity,
119 const NumberFormat &fmt,
120 const PluralRules &rules,
121 UnicodeString &appendTo,
122 FieldPosition &pos,
123 UErrorCode &status) const {
124 if (U_FAILURE(status)) {
125 return appendTo;
126 }
127 UnicodeString count;
128 const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
129 if (decFmt != NULL) {
130 FixedDecimal fd = decFmt->getFixedDecimal(quantity, status);
131 if (U_FAILURE(status)) {
132 return appendTo;
133 }
134 count = rules.select(fd);
135 } else {
136 if (quantity.getType() == Formattable::kDouble) {
137 count = rules.select(quantity.getDouble());
138 } else if (quantity.getType() == Formattable::kLong) {
139 count = rules.select(quantity.getLong());
140 } else if (quantity.getType() == Formattable::kInt64) {
141 count = rules.select((double) quantity.getInt64());
142 } else {
143 status = U_ILLEGAL_ARGUMENT_ERROR;
144 return appendTo;
145 }
146 }
147 CharString buffer;
148 buffer.appendInvariantChars(count, status);
149 if (U_FAILURE(status)) {
150 return appendTo;
151 }
152 int32_t pluralIndex = getPluralIndex(buffer.data());
153 if (pluralIndex == -1) {
154 pluralIndex = 0;
155 }
156 const SimplePatternFormatter *pattern = formatters[pluralIndex];
157 if (pattern == NULL) {
158 pattern = formatters[0];
159 }
160 if (pattern == NULL) {
161 status = U_INVALID_STATE_ERROR;
162 return appendTo;
163 }
164 UnicodeString formattedNumber;
165 FieldPosition fpos(pos.getField());
166 fmt.format(quantity, formattedNumber, fpos, status);
167 const UnicodeString *params[1] = {&formattedNumber};
168 int32_t offsets[1];
169 pattern->format(params, LENGTHOF(params), appendTo, offsets, LENGTHOF(offsets), status);
170 if (offsets[0] != -1) {
171 if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
172 pos.setBeginIndex(fpos.getBeginIndex() + offsets[0]);
173 pos.setEndIndex(fpos.getEndIndex() + offsets[0]);
174 }
175 }
176 return appendTo;
177}
178
179U_NAMESPACE_END
180
181#endif /* #if !UCONFIG_NO_FORMATTING */