Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/intl/icu/source/i18n/number_modifiers.h
Line
Count
Source (jump to first uncovered line)
1
// © 2017 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
4
#include "unicode/utypes.h"
5
6
#if !UCONFIG_NO_FORMATTING
7
#ifndef __NUMBER_MODIFIERS_H__
8
#define __NUMBER_MODIFIERS_H__
9
10
#include <algorithm>
11
#include <cstdint>
12
#include "unicode/uniset.h"
13
#include "unicode/simpleformatter.h"
14
#include "standardplural.h"
15
#include "number_stringbuilder.h"
16
#include "number_types.h"
17
18
U_NAMESPACE_BEGIN namespace number {
19
namespace impl {
20
21
/**
22
 * The canonical implementation of {@link Modifier}, containing a prefix and suffix string.
23
 * TODO: This is not currently being used by real code and could be removed.
24
 */
25
class U_I18N_API ConstantAffixModifier : public Modifier, public UObject {
26
  public:
27
    ConstantAffixModifier(const UnicodeString &prefix, const UnicodeString &suffix, Field field,
28
                          bool strong)
29
0
            : fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {}
30
31
    int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
32
                  UErrorCode &status) const U_OVERRIDE;
33
34
    int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE;
35
36
    int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE;
37
38
    bool isStrong() const U_OVERRIDE;
39
40
  private:
41
    UnicodeString fPrefix;
42
    UnicodeString fSuffix;
43
    Field fField;
44
    bool fStrong;
45
};
46
47
/**
48
 * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter}
49
 * pattern.
50
 */
51
class U_I18N_API SimpleModifier : public Modifier, public UMemory {
52
  public:
53
    SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong);
54
55
    // Default constructor for LongNameHandler.h
56
    SimpleModifier();
57
58
    int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
59
                  UErrorCode &status) const U_OVERRIDE;
60
61
    int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE;
62
63
    int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE;
64
65
    bool isStrong() const U_OVERRIDE;
66
67
    /**
68
     * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because
69
     * DoubleSidedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
70
     *
71
     * <p>
72
     * Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices
73
     * <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start index and after the
74
     * end index.
75
     *
76
     * <p>
77
     * This is well-defined only for patterns with exactly one argument.
78
     *
79
     * @param result
80
     *            The StringBuilder containing the value argument.
81
     * @param startIndex
82
     *            The left index of the value within the string builder.
83
     * @param endIndex
84
     *            The right index of the value within the string builder.
85
     * @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
86
     */
87
    int32_t
88
    formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex, Field field,
89
                         UErrorCode &status) const;
90
91
  private:
92
    UnicodeString fCompiledPattern;
93
    Field fField;
94
    bool fStrong;
95
    int32_t fPrefixLength;
96
    int32_t fSuffixOffset;
97
    int32_t fSuffixLength;
98
};
99
100
/**
101
 * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed
102
 * based on the contents of two {@link NumberStringBuilder} instances (one for the prefix, one for the suffix).
103
 */
104
class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
105
  public:
106
    ConstantMultiFieldModifier(
107
            const NumberStringBuilder &prefix,
108
            const NumberStringBuilder &suffix,
109
            bool overwrite,
110
            bool strong)
111
      : fPrefix(prefix),
112
        fSuffix(suffix),
113
        fOverwrite(overwrite),
114
0
        fStrong(strong) {}
115
116
    int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
117
                  UErrorCode &status) const U_OVERRIDE;
118
119
    int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE;
120
121
    int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE;
122
123
    bool isStrong() const U_OVERRIDE;
124
125
  protected:
126
    // NOTE: In Java, these are stored as array pointers. In C++, the NumberStringBuilder is stored by
127
    // value and is treated internally as immutable.
128
    NumberStringBuilder fPrefix;
129
    NumberStringBuilder fSuffix;
130
    bool fOverwrite;
131
    bool fStrong;
132
};
133
134
/** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */
135
class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModifier {
136
  public:
137
    /** Safe code path */
138
    CurrencySpacingEnabledModifier(
139
            const NumberStringBuilder &prefix,
140
            const NumberStringBuilder &suffix,
141
            bool overwrite,
142
            bool strong,
143
            const DecimalFormatSymbols &symbols,
144
            UErrorCode &status);
145
146
    int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
147
                  UErrorCode &status) const U_OVERRIDE;
148
149
    /** Unsafe code path */
150
    static int32_t
151
    applyCurrencySpacing(NumberStringBuilder &output, int32_t prefixStart, int32_t prefixLen,
152
                         int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols,
153
                         UErrorCode &status);
154
155
  private:
156
    UnicodeSet fAfterPrefixUnicodeSet;
157
    UnicodeString fAfterPrefixInsert;
158
    UnicodeSet fBeforeSuffixUnicodeSet;
159
    UnicodeString fBeforeSuffixInsert;
160
161
    enum EAffix {
162
        PREFIX, SUFFIX
163
    };
164
165
    enum EPosition {
166
        IN_CURRENCY, IN_NUMBER
167
    };
168
169
    /** Unsafe code path */
170
    static int32_t applyCurrencySpacingAffix(NumberStringBuilder &output, int32_t index, EAffix affix,
171
                                             const DecimalFormatSymbols &symbols, UErrorCode &status);
172
173
    static UnicodeSet
174
    getUnicodeSet(const DecimalFormatSymbols &symbols, EPosition position, EAffix affix,
175
                  UErrorCode &status);
176
177
    static UnicodeString
178
    getInsertString(const DecimalFormatSymbols &symbols, EAffix affix, UErrorCode &status);
179
};
180
181
/** A Modifier that does not do anything. */
182
class U_I18N_API EmptyModifier : public Modifier, public UMemory {
183
  public:
184
0
    explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {}
185
186
    int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
187
0
                  UErrorCode &status) const U_OVERRIDE {
188
0
        (void)output;
189
0
        (void)leftIndex;
190
0
        (void)rightIndex;
191
0
        (void)status;
192
0
        return 0;
193
0
    }
194
195
0
    int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE {
196
0
        (void)status;
197
0
        return 0;
198
0
    }
199
200
0
    int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE {
201
0
        (void)status;
202
0
        return 0;
203
0
    }
204
205
0
    bool isStrong() const U_OVERRIDE {
206
0
        return fStrong;
207
0
    }
208
209
  private:
210
    bool fStrong;
211
};
212
213
/**
214
 * A ParameterizedModifier by itself is NOT a Modifier. Rather, it wraps a data structure containing two or more
215
 * Modifiers and returns the modifier appropriate for the current situation.
216
 */
217
class U_I18N_API ParameterizedModifier : public UMemory {
218
  public:
219
    // NOTE: mods is zero-initialized (to nullptr)
220
0
    ParameterizedModifier() : mods() {
221
0
    }
222
223
    // No copying!
224
    ParameterizedModifier(const ParameterizedModifier &other) = delete;
225
226
0
    ~ParameterizedModifier() {
227
0
        for (const Modifier *mod : mods) {
228
0
            delete mod;
229
0
        }
230
0
    }
231
232
    void adoptPositiveNegativeModifiers(
233
0
            const Modifier *positive, const Modifier *zero, const Modifier *negative) {
234
0
        mods[2] = positive;
235
0
        mods[1] = zero;
236
0
        mods[0] = negative;
237
0
    }
238
239
    /** The modifier is ADOPTED. */
240
0
    void adoptSignPluralModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) {
241
0
        mods[getModIndex(signum, plural)] = mod;
242
0
    }
243
244
    /** Returns a reference to the modifier; no ownership change. */
245
0
    const Modifier *getModifier(int8_t signum) const {
246
0
        return mods[signum + 1];
247
0
    }
248
249
    /** Returns a reference to the modifier; no ownership change. */
250
0
    const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const {
251
0
        return mods[getModIndex(signum, plural)];
252
0
    }
253
254
  private:
255
    const Modifier *mods[3 * StandardPlural::COUNT];
256
257
0
    inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) {
258
0
        return static_cast<int32_t>(plural) * 3 + (signum + 1);
259
0
    }
260
};
261
262
} // namespace impl
263
} // namespace number
264
U_NAMESPACE_END
265
266
267
#endif //__NUMBER_MODIFIERS_H__
268
269
#endif /* #if !UCONFIG_NO_FORMATTING */