1 // © 2017 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 #include "unicode/utypes.h"
6 #if !UCONFIG_NO_FORMATTING
7 #ifndef __NUMBER_MODIFIERS_H__
8 #define __NUMBER_MODIFIERS_H__
12 #include "unicode/uniset.h"
13 #include "unicode/simpleformatter.h"
14 #include "standardplural.h"
15 #include "number_stringbuilder.h"
16 #include "number_types.h"
18 U_NAMESPACE_BEGIN
namespace number
{
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.
25 class U_I18N_API ConstantAffixModifier
: public Modifier
, public UObject
{
27 ConstantAffixModifier(const UnicodeString
&prefix
, const UnicodeString
&suffix
, Field field
,
29 : fPrefix(prefix
), fSuffix(suffix
), fField(field
), fStrong(strong
) {}
31 int32_t apply(NumberStringBuilder
&output
, int32_t leftIndex
, int32_t rightIndex
,
32 UErrorCode
&status
) const U_OVERRIDE
;
34 int32_t getPrefixLength(UErrorCode
&status
) const U_OVERRIDE
;
36 int32_t getCodePointCount(UErrorCode
&status
) const U_OVERRIDE
;
38 bool isStrong() const U_OVERRIDE
;
41 UnicodeString fPrefix
;
42 UnicodeString fSuffix
;
48 * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter}
51 class U_I18N_API SimpleModifier
: public Modifier
, public UMemory
{
53 SimpleModifier(const SimpleFormatter
&simpleFormatter
, Field field
, bool strong
);
55 // Default constructor for LongNameHandler.h
58 int32_t apply(NumberStringBuilder
&output
, int32_t leftIndex
, int32_t rightIndex
,
59 UErrorCode
&status
) const U_OVERRIDE
;
61 int32_t getPrefixLength(UErrorCode
&status
) const U_OVERRIDE
;
63 int32_t getCodePointCount(UErrorCode
&status
) const U_OVERRIDE
;
65 bool isStrong() const U_OVERRIDE
;
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.
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
77 * This is well-defined only for patterns with exactly one argument.
80 * The StringBuilder containing the value argument.
82 * The left index of the value within the string builder.
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.
88 formatAsPrefixSuffix(NumberStringBuilder
&result
, int32_t startIndex
, int32_t endIndex
, Field field
,
89 UErrorCode
&status
) const;
92 UnicodeString fCompiledPattern
;
95 int32_t fPrefixLength
;
96 int32_t fSuffixOffset
;
97 int32_t fSuffixLength
;
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).
104 class U_I18N_API ConstantMultiFieldModifier
: public Modifier
, public UMemory
{
106 ConstantMultiFieldModifier(
107 const NumberStringBuilder
&prefix
,
108 const NumberStringBuilder
&suffix
,
113 fOverwrite(overwrite
),
116 int32_t apply(NumberStringBuilder
&output
, int32_t leftIndex
, int32_t rightIndex
,
117 UErrorCode
&status
) const U_OVERRIDE
;
119 int32_t getPrefixLength(UErrorCode
&status
) const U_OVERRIDE
;
121 int32_t getCodePointCount(UErrorCode
&status
) const U_OVERRIDE
;
123 bool isStrong() const U_OVERRIDE
;
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
;
134 /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */
135 class U_I18N_API CurrencySpacingEnabledModifier
: public ConstantMultiFieldModifier
{
137 /** Safe code path */
138 CurrencySpacingEnabledModifier(
139 const NumberStringBuilder
&prefix
,
140 const NumberStringBuilder
&suffix
,
143 const DecimalFormatSymbols
&symbols
,
146 int32_t apply(NumberStringBuilder
&output
, int32_t leftIndex
, int32_t rightIndex
,
147 UErrorCode
&status
) const U_OVERRIDE
;
149 /** Unsafe code path */
151 applyCurrencySpacing(NumberStringBuilder
&output
, int32_t prefixStart
, int32_t prefixLen
,
152 int32_t suffixStart
, int32_t suffixLen
, const DecimalFormatSymbols
&symbols
,
156 UnicodeSet fAfterPrefixUnicodeSet
;
157 UnicodeString fAfterPrefixInsert
;
158 UnicodeSet fBeforeSuffixUnicodeSet
;
159 UnicodeString fBeforeSuffixInsert
;
166 IN_CURRENCY
, IN_NUMBER
169 /** Unsafe code path */
170 static int32_t applyCurrencySpacingAffix(NumberStringBuilder
&output
, int32_t index
, EAffix affix
,
171 const DecimalFormatSymbols
&symbols
, UErrorCode
&status
);
174 getUnicodeSet(const DecimalFormatSymbols
&symbols
, EPosition position
, EAffix affix
,
178 getInsertString(const DecimalFormatSymbols
&symbols
, EAffix affix
, UErrorCode
&status
);
181 /** A Modifier that does not do anything. */
182 class U_I18N_API EmptyModifier
: public Modifier
, public UMemory
{
184 explicit EmptyModifier(bool isStrong
) : fStrong(isStrong
) {}
186 int32_t apply(NumberStringBuilder
&output
, int32_t leftIndex
, int32_t rightIndex
,
187 UErrorCode
&status
) const U_OVERRIDE
{
195 int32_t getPrefixLength(UErrorCode
&status
) const U_OVERRIDE
{
200 int32_t getCodePointCount(UErrorCode
&status
) const U_OVERRIDE
{
205 bool isStrong() const U_OVERRIDE
{
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.
217 class U_I18N_API ParameterizedModifier
: public UMemory
{
219 // NOTE: mods is zero-initialized (to nullptr)
220 ParameterizedModifier() : mods() {
224 ParameterizedModifier(const ParameterizedModifier
&other
) = delete;
226 ~ParameterizedModifier() {
227 for (const Modifier
*mod
: mods
) {
232 void adoptPositiveNegativeModifiers(
233 const Modifier
*positive
, const Modifier
*zero
, const Modifier
*negative
) {
239 /** The modifier is ADOPTED. */
240 void adoptSignPluralModifier(int8_t signum
, StandardPlural::Form plural
, const Modifier
*mod
) {
241 mods
[getModIndex(signum
, plural
)] = mod
;
244 /** Returns a reference to the modifier; no ownership change. */
245 const Modifier
*getModifier(int8_t signum
) const {
246 return mods
[signum
+ 1];
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
)];
255 const Modifier
*mods
[3 * StandardPlural::COUNT
];
257 inline static int32_t getModIndex(int8_t signum
, StandardPlural::Form plural
) {
258 return static_cast<int32_t>(plural
) * 3 + (signum
+ 1);
263 } // namespace number
267 #endif //__NUMBER_MODIFIERS_H__
269 #endif /* #if !UCONFIG_NO_FORMATTING */