]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/number_modifiers.h
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / number_modifiers.h
CommitLineData
0f5d89e8
A
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
18U_NAMESPACE_BEGIN namespace number {
19namespace 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 */
25class U_I18N_API ConstantAffixModifier : public Modifier, public UObject {
26 public:
27 ConstantAffixModifier(const UnicodeString &prefix, const UnicodeString &suffix, Field field,
28 bool strong)
29 : 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 */
51class 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 */
104class 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 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. */
135class 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. */
182class U_I18N_API EmptyModifier : public Modifier, public UMemory {
183 public:
184 explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {}
185
186 int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
187 UErrorCode &status) const U_OVERRIDE {
188 (void)output;
189 (void)leftIndex;
190 (void)rightIndex;
191 (void)status;
192 return 0;
193 }
194
195 int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE {
196 (void)status;
197 return 0;
198 }
199
200 int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE {
201 (void)status;
202 return 0;
203 }
204
205 bool isStrong() const U_OVERRIDE {
206 return fStrong;
207 }
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 */
217class U_I18N_API ParameterizedModifier : public UMemory {
218 public:
219 // NOTE: mods is zero-initialized (to nullptr)
220 ParameterizedModifier() : mods() {
221 }
222
223 // No copying!
224 ParameterizedModifier(const ParameterizedModifier &other) = delete;
225
226 ~ParameterizedModifier() {
227 for (const Modifier *mod : mods) {
228 delete mod;
229 }
230 }
231
232 void adoptPositiveNegativeModifiers(
233 const Modifier *positive, const Modifier *zero, const Modifier *negative) {
234 mods[2] = positive;
235 mods[1] = zero;
236 mods[0] = negative;
237 }
238
239 /** The modifier is ADOPTED. */
240 void adoptSignPluralModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) {
241 mods[getModIndex(signum, plural)] = mod;
242 }
243
244 /** Returns a reference to the modifier; no ownership change. */
245 const Modifier *getModifier(int8_t signum) const {
246 return mods[signum + 1];
247 }
248
249 /** Returns a reference to the modifier; no ownership change. */
250 const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const {
251 return mods[getModIndex(signum, plural)];
252 }
253
254 private:
255 const Modifier *mods[3 * StandardPlural::COUNT];
256
257 inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) {
258 return static_cast<int32_t>(plural) * 3 + (signum + 1);
259 }
260};
261
262} // namespace impl
263} // namespace number
264U_NAMESPACE_END
265
266
267#endif //__NUMBER_MODIFIERS_H__
268
269#endif /* #if !UCONFIG_NO_FORMATTING */