1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
|
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
#include <_foundation_unicode/utypes.h>
#if !UCONFIG_NO_FORMATTING
#ifndef __NUMBER_PATTERNMODIFIER_H__
#define __NUMBER_PATTERNMODIFIER_H__
#include "standardplural.h"
#include <_foundation_unicode/numberformatter.h>
#include "number_patternstring.h"
#include "number_types.h"
#include "number_modifiers.h"
#include "number_utils.h"
#include "number_currencysymbols.h"
U_NAMESPACE_BEGIN
// Export an explicit template instantiation of the LocalPointer that is used as a
// data member of AdoptingModifierStore.
// (When building DLLs for Windows this is required.)
#if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
#if defined(_MSC_VER)
// Ignore warning 4661 as LocalPointerBase does not use operator== or operator!=
#pragma warning(push)
#pragma warning(disable : 4661)
#endif
template class U_I18N_API LocalPointerBase<number::impl::AdoptingModifierStore>;
template class U_I18N_API LocalPointer<number::impl::AdoptingModifierStore>;
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif
namespace number {
namespace impl {
// Forward declaration
class MutablePatternModifier;
// Exported as U_I18N_API because it is needed for the unit test PatternModifierTest
class U_I18N_API ImmutablePatternModifier : public MicroPropsGenerator, public UMemory {
public:
~ImmutablePatternModifier() override = default;
void processQuantity(DecimalQuantity&, MicroProps& micros, UErrorCode& status) const override;
void applyToMicros(MicroProps& micros, const DecimalQuantity& quantity, UErrorCode& status) const;
const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const;
// Non-const method:
void addToChain(const MicroPropsGenerator* parent);
private:
ImmutablePatternModifier(AdoptingModifierStore* pm, const PluralRules* rules);
const LocalPointer<AdoptingModifierStore> pm;
const PluralRules* rules;
const MicroPropsGenerator* parent;
friend class MutablePatternModifier;
};
/**
* This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes in
* {@link Modifier#apply}.
*
* <p>
* In addition to being a Modifier, this class contains the business logic for substituting the correct locale symbols
* into the affixes of the decimal format pattern.
*
* <p>
* In order to use this class, create a new instance and call the following four setters: {@link #setPatternInfo},
* {@link #setPatternAttributes}, {@link #setSymbols}, and {@link #setNumberProperties}. After calling these four
* setters, the instance will be ready for use as a Modifier.
*
* <p>
* This is a MUTABLE, NON-THREAD-SAFE class designed for performance. Do NOT save references to this or attempt to use
* it from multiple threads! Instead, you can obtain a safe, immutable decimal format pattern modifier by calling
* {@link MutablePatternModifier#createImmutable}, in effect treating this instance as a builder for the immutable
* variant.
*/
class U_I18N_API MutablePatternModifier
: public MicroPropsGenerator,
public Modifier,
public SymbolProvider,
public UMemory {
public:
~MutablePatternModifier() override = default;
/**
* @param isStrong
* Whether the modifier should be considered strong. For more information, see
* {@link Modifier#isStrong()}. Most of the time, decimal format pattern modifiers should be considered
* as non-strong.
*/
explicit MutablePatternModifier(bool isStrong);
/**
* Sets a reference to the parsed decimal format pattern, usually obtained from
* {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of {@link AffixPatternProvider} is
* accepted.
*
* @param field
* Which field to use for literal characters in the pattern.
*/
void setPatternInfo(const AffixPatternProvider *patternInfo, Field field);
/**
* Sets attributes that imply changes to the literal interpretation of the pattern string affixes.
*
* @param signDisplay
* Whether to force a plus sign on positive numbers.
* @param perMille
* Whether to substitute the percent sign in the pattern with a permille sign.
* @param approximately
* Whether to prepend approximately to the sign
*/
void setPatternAttributes(UNumberSignDisplay signDisplay, bool perMille, bool approximately);
/**
* Sets locale-specific details that affect the symbols substituted into the pattern string affixes.
*
* @param symbols
* The desired instance of DecimalFormatSymbols.
* @param currency
* The currency to be used when substituting currency values into the affixes.
* @param unitWidth
* The width used to render currencies.
* @param rules
* Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be determined from the
* convenience method {@link #needsPlurals()}.
* @param status
* Set if an error occurs while loading currency data.
*/
void setSymbols(const DecimalFormatSymbols* symbols, const CurrencyUnit& currency,
UNumberUnitWidth unitWidth, const PluralRules* rules, UErrorCode& status);
/**
* Sets attributes of the current number being processed.
*
* @param signum
* -1 if negative; +1 if positive; or 0 if zero.
* @param plural
* The plural form of the number, required only if the pattern contains the triple
* currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
*/
void setNumberProperties(Signum signum, StandardPlural::Form plural);
/**
* Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order to localize.
* This is currently true only if there is a currency long name placeholder in the pattern ("¤¤¤").
*/
bool needsPlurals() const;
/** Creates a quantity-dependent Modifier for the specified plural form. */
AdoptingSignumModifierStore createImmutableForPlural(StandardPlural::Form plural, UErrorCode& status);
/**
* Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which is immutable
* and can be saved for future use. The number properties in the current instance are mutated; all other properties
* are left untouched.
*
* <p>
* The resulting modifier cannot be used in a QuantityChain.
*
* <p>
* CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
*
* @return An immutable that supports both positive and negative numbers.
*/
ImmutablePatternModifier *createImmutable(UErrorCode &status);
MicroPropsGenerator &addToChain(const MicroPropsGenerator *parent);
void processQuantity(DecimalQuantity &, MicroProps µs, UErrorCode &status) const override;
int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const override;
int32_t getPrefixLength() const override;
int32_t getCodePointCount() const override;
bool isStrong() const override;
bool containsField(Field field) const override;
void getParameters(Parameters& output) const override;
bool semanticallyEquivalent(const Modifier& other) const override;
/**
* Returns the string that substitutes a given symbol type in a pattern.
*/
UnicodeString getSymbol(AffixPatternType type) const override;
/**
* Returns the currency symbol for the unit width specified in setSymbols()
*/
UnicodeString getCurrencySymbolForUnitWidth(UErrorCode& status) const;
UnicodeString toUnicodeString() const;
private:
// Modifier details (initialized in constructor)
const bool fStrong;
// Pattern details (initialized in setPatternInfo and setPatternAttributes)
const AffixPatternProvider *fPatternInfo;
Field fField;
UNumberSignDisplay fSignDisplay;
bool fPerMilleReplacesPercent;
bool fApproximately;
// Symbol details (initialized in setSymbols)
const DecimalFormatSymbols *fSymbols;
UNumberUnitWidth fUnitWidth;
CurrencySymbols fCurrencySymbols;
const PluralRules *fRules;
// Number details (initialized in setNumberProperties)
Signum fSignum;
StandardPlural::Form fPlural;
// QuantityChain details (initialized in addToChain)
const MicroPropsGenerator *fParent;
// Transient fields for rendering
UnicodeString currentAffix;
/**
* Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency spacing support
* if required.
*
* <p>
* CREATES A NEW HEAP OBJECT; THE CALLER GETS OWNERSHIP.
*
* @param a
* A working FormattedStringBuilder object; passed from the outside to prevent the need to create many new
* instances if this method is called in a loop.
* @param b
* Another working FormattedStringBuilder object.
* @return The constant modifier object.
*/
ConstantMultiFieldModifier *createConstantModifier(UErrorCode &status);
int32_t insertPrefix(FormattedStringBuilder &sb, int position, UErrorCode &status);
int32_t insertSuffix(FormattedStringBuilder &sb, int position, UErrorCode &status);
void prepareAffix(bool isPrefix);
};
} // namespace impl
} // namespace number
U_NAMESPACE_END
#endif //__NUMBER_PATTERNMODIFIER_H__
#endif /* #if !UCONFIG_NO_FORMATTING */
|