Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/i18n/quantityformatter.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
******************************************************************************
5
* Copyright (C) 2014-2016, International Business Machines
6
* Corporation and others.  All Rights Reserved.
7
******************************************************************************
8
* quantityformatter.cpp
9
*/
10
11
#include "unicode/utypes.h"
12
13
#if !UCONFIG_NO_FORMATTING
14
15
#include "unicode/simpleformatter.h"
16
#include "quantityformatter.h"
17
#include "uassert.h"
18
#include "unicode/unistr.h"
19
#include "unicode/decimfmt.h"
20
#include "cstring.h"
21
#include "unicode/plurrule.h"
22
#include "charstr.h"
23
#include "unicode/fmtable.h"
24
#include "unicode/fieldpos.h"
25
#include "standardplural.h"
26
#include "uassert.h"
27
#include "number_decimalquantity.h"
28
29
U_NAMESPACE_BEGIN
30
31
0
QuantityFormatter::QuantityFormatter() {
32
0
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
33
0
        formatters[i] = NULL;
34
0
    }
35
0
}
36
37
0
QuantityFormatter::QuantityFormatter(const QuantityFormatter &other) {
38
0
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
39
0
        if (other.formatters[i] == NULL) {
40
0
            formatters[i] = NULL;
41
0
        } else {
42
0
            formatters[i] = new SimpleFormatter(*other.formatters[i]);
43
0
        }
44
0
    }
45
0
}
46
47
QuantityFormatter &QuantityFormatter::operator=(
48
0
        const QuantityFormatter& other) {
49
0
    if (this == &other) {
50
0
        return *this;
51
0
    }
52
0
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
53
0
        delete formatters[i];
54
0
        if (other.formatters[i] == NULL) {
55
0
            formatters[i] = NULL;
56
0
        } else {
57
0
            formatters[i] = new SimpleFormatter(*other.formatters[i]);
58
0
        }
59
0
    }
60
0
    return *this;
61
0
}
62
63
0
QuantityFormatter::~QuantityFormatter() {
64
0
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
65
0
        delete formatters[i];
66
0
    }
67
0
}
68
69
0
void QuantityFormatter::reset() {
70
0
    for (int32_t i = 0; i < UPRV_LENGTHOF(formatters); ++i) {
71
0
        delete formatters[i];
72
0
        formatters[i] = NULL;
73
0
    }
74
0
}
75
76
UBool QuantityFormatter::addIfAbsent(
77
        const char *variant,
78
        const UnicodeString &rawPattern,
79
0
        UErrorCode &status) {
80
0
    int32_t pluralIndex = StandardPlural::indexFromString(variant, status);
81
0
    if (U_FAILURE(status)) {
82
0
        return FALSE;
83
0
    }
84
0
    if (formatters[pluralIndex] != NULL) {
85
0
        return TRUE;
86
0
    }
87
0
    SimpleFormatter *newFmt = new SimpleFormatter(rawPattern, 0, 1, status);
88
0
    if (newFmt == NULL) {
89
0
        status = U_MEMORY_ALLOCATION_ERROR;
90
0
        return FALSE;
91
0
    }
92
0
    if (U_FAILURE(status)) {
93
0
        delete newFmt;
94
0
        return FALSE;
95
0
    }
96
0
    formatters[pluralIndex] = newFmt;
97
0
    return TRUE;
98
0
}
99
100
0
UBool QuantityFormatter::isValid() const {
101
0
    return formatters[StandardPlural::OTHER] != NULL;
102
0
}
103
104
const SimpleFormatter *QuantityFormatter::getByVariant(
105
0
        const char *variant) const {
106
0
    U_ASSERT(isValid());
107
0
    int32_t pluralIndex = StandardPlural::indexOrOtherIndexFromString(variant);
108
0
    const SimpleFormatter *pattern = formatters[pluralIndex];
109
0
    if (pattern == NULL) {
110
0
        pattern = formatters[StandardPlural::OTHER];
111
0
    }
112
0
    return pattern;
113
0
}
114
115
UnicodeString &QuantityFormatter::format(
116
            const Formattable &number,
117
            const NumberFormat &fmt,
118
            const PluralRules &rules,
119
            UnicodeString &appendTo,
120
            FieldPosition &pos,
121
0
            UErrorCode &status) const {
122
0
    UnicodeString formattedNumber;
123
0
    StandardPlural::Form p = selectPlural(number, fmt, rules, formattedNumber, pos, status);
124
0
    if (U_FAILURE(status)) {
125
0
        return appendTo;
126
0
    }
127
0
    const SimpleFormatter *pattern = formatters[p];
128
0
    if (pattern == NULL) {
129
0
        pattern = formatters[StandardPlural::OTHER];
130
0
        if (pattern == NULL) {
131
0
            status = U_INVALID_STATE_ERROR;
132
0
            return appendTo;
133
0
        }
134
0
    }
135
0
    return format(*pattern, formattedNumber, appendTo, pos, status);
136
0
}
137
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.
140
141
StandardPlural::Form QuantityFormatter::selectPlural(
142
            const Formattable &number,
143
            const NumberFormat &fmt,
144
            const PluralRules &rules,
145
            UnicodeString &formattedNumber,
146
            FieldPosition &pos,
147
0
            UErrorCode &status) {
148
0
    if (U_FAILURE(status)) {
149
0
        return StandardPlural::OTHER;
150
0
    }
151
0
    UnicodeString pluralKeyword;
152
0
    const DecimalFormat *decFmt = dynamic_cast<const DecimalFormat *>(&fmt);
153
0
    if (decFmt != NULL) {
154
0
        number::impl::DecimalQuantity dq;
155
0
        decFmt->formatToDecimalQuantity(number, dq, status);
156
0
        if (U_FAILURE(status)) {
157
0
            return StandardPlural::OTHER;
158
0
        }
159
0
        pluralKeyword = rules.select(dq);
160
0
        decFmt->format(number, formattedNumber, pos, status);
161
0
    } else {
162
0
        if (number.getType() == Formattable::kDouble) {
163
0
            pluralKeyword = rules.select(number.getDouble());
164
0
        } else if (number.getType() == Formattable::kLong) {
165
0
            pluralKeyword = rules.select(number.getLong());
166
0
        } else if (number.getType() == Formattable::kInt64) {
167
0
            pluralKeyword = rules.select((double) number.getInt64());
168
0
        } else {
169
0
            status = U_ILLEGAL_ARGUMENT_ERROR;
170
0
            return StandardPlural::OTHER;
171
0
        }
172
0
        fmt.format(number, formattedNumber, pos, status);
173
0
    }
174
0
    return StandardPlural::orOtherFromString(pluralKeyword);
175
0
}
176
177
UnicodeString &QuantityFormatter::format(
178
            const SimpleFormatter &pattern,
179
            const UnicodeString &value,
180
            UnicodeString &appendTo,
181
            FieldPosition &pos,
182
0
            UErrorCode &status) {
183
0
    if (U_FAILURE(status)) {
184
0
        return appendTo;
185
0
    }
186
0
    const UnicodeString *param = &value;
187
0
    int32_t offset;
188
0
    pattern.formatAndAppend(&param, 1, appendTo, &offset, 1, status);
189
0
    if (pos.getBeginIndex() != 0 || pos.getEndIndex() != 0) {
190
0
        if (offset >= 0) {
191
0
            pos.setBeginIndex(pos.getBeginIndex() + offset);
192
0
            pos.setEndIndex(pos.getEndIndex() + offset);
193
0
        } else {
194
0
            pos.setBeginIndex(0);
195
0
            pos.setEndIndex(0);
196
0
        }
197
0
    }
198
0
    return appendTo;
199
0
}
200
201
U_NAMESPACE_END
202
203
#endif /* #if !UCONFIG_NO_FORMATTING */