1*0e209d39SAndroid Build Coastguard Worker // © 2017 and later: Unicode, Inc. and others. 2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html 3*0e209d39SAndroid Build Coastguard Worker 4*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h" 5*0e209d39SAndroid Build Coastguard Worker 6*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_FORMATTING 7*0e209d39SAndroid Build Coastguard Worker #ifndef __NUMBER_MODIFIERS_H__ 8*0e209d39SAndroid Build Coastguard Worker #define __NUMBER_MODIFIERS_H__ 9*0e209d39SAndroid Build Coastguard Worker 10*0e209d39SAndroid Build Coastguard Worker #include <algorithm> 11*0e209d39SAndroid Build Coastguard Worker #include <cstdint> 12*0e209d39SAndroid Build Coastguard Worker #include "unicode/uniset.h" 13*0e209d39SAndroid Build Coastguard Worker #include "unicode/simpleformatter.h" 14*0e209d39SAndroid Build Coastguard Worker #include "standardplural.h" 15*0e209d39SAndroid Build Coastguard Worker #include "formatted_string_builder.h" 16*0e209d39SAndroid Build Coastguard Worker #include "number_types.h" 17*0e209d39SAndroid Build Coastguard Worker 18*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN 19*0e209d39SAndroid Build Coastguard Worker namespace number::impl { 20*0e209d39SAndroid Build Coastguard Worker 21*0e209d39SAndroid Build Coastguard Worker /** 22*0e209d39SAndroid Build Coastguard Worker * The canonical implementation of {@link Modifier}, containing a prefix and suffix string. 23*0e209d39SAndroid Build Coastguard Worker * TODO: This is not currently being used by real code and could be removed. 24*0e209d39SAndroid Build Coastguard Worker */ 25*0e209d39SAndroid Build Coastguard Worker class U_I18N_API ConstantAffixModifier : public Modifier, public UObject { 26*0e209d39SAndroid Build Coastguard Worker public: ConstantAffixModifier(const UnicodeString & prefix,const UnicodeString & suffix,Field field,bool strong)27*0e209d39SAndroid Build Coastguard Worker ConstantAffixModifier(const UnicodeString &prefix, const UnicodeString &suffix, Field field, 28*0e209d39SAndroid Build Coastguard Worker bool strong) 29*0e209d39SAndroid Build Coastguard Worker : fPrefix(prefix), fSuffix(suffix), fField(field), fStrong(strong) {} 30*0e209d39SAndroid Build Coastguard Worker 31*0e209d39SAndroid Build Coastguard Worker int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, 32*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const override; 33*0e209d39SAndroid Build Coastguard Worker 34*0e209d39SAndroid Build Coastguard Worker int32_t getPrefixLength() const override; 35*0e209d39SAndroid Build Coastguard Worker 36*0e209d39SAndroid Build Coastguard Worker int32_t getCodePointCount() const override; 37*0e209d39SAndroid Build Coastguard Worker 38*0e209d39SAndroid Build Coastguard Worker bool isStrong() const override; 39*0e209d39SAndroid Build Coastguard Worker 40*0e209d39SAndroid Build Coastguard Worker bool containsField(Field field) const override; 41*0e209d39SAndroid Build Coastguard Worker 42*0e209d39SAndroid Build Coastguard Worker void getParameters(Parameters& output) const override; 43*0e209d39SAndroid Build Coastguard Worker 44*0e209d39SAndroid Build Coastguard Worker bool strictEquals(const Modifier& other) const override; 45*0e209d39SAndroid Build Coastguard Worker 46*0e209d39SAndroid Build Coastguard Worker private: 47*0e209d39SAndroid Build Coastguard Worker UnicodeString fPrefix; 48*0e209d39SAndroid Build Coastguard Worker UnicodeString fSuffix; 49*0e209d39SAndroid Build Coastguard Worker Field fField; 50*0e209d39SAndroid Build Coastguard Worker bool fStrong; 51*0e209d39SAndroid Build Coastguard Worker }; 52*0e209d39SAndroid Build Coastguard Worker 53*0e209d39SAndroid Build Coastguard Worker /** 54*0e209d39SAndroid Build Coastguard Worker * The second primary implementation of {@link Modifier}, this one consuming a {@link SimpleFormatter} 55*0e209d39SAndroid Build Coastguard Worker * pattern. 56*0e209d39SAndroid Build Coastguard Worker */ 57*0e209d39SAndroid Build Coastguard Worker class U_I18N_API SimpleModifier : public Modifier, public UMemory { 58*0e209d39SAndroid Build Coastguard Worker public: 59*0e209d39SAndroid Build Coastguard Worker SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong); 60*0e209d39SAndroid Build Coastguard Worker 61*0e209d39SAndroid Build Coastguard Worker SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong, 62*0e209d39SAndroid Build Coastguard Worker const Modifier::Parameters parameters); 63*0e209d39SAndroid Build Coastguard Worker 64*0e209d39SAndroid Build Coastguard Worker // Default constructor for LongNameHandler.h 65*0e209d39SAndroid Build Coastguard Worker SimpleModifier(); 66*0e209d39SAndroid Build Coastguard Worker 67*0e209d39SAndroid Build Coastguard Worker int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, 68*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const override; 69*0e209d39SAndroid Build Coastguard Worker 70*0e209d39SAndroid Build Coastguard Worker int32_t getPrefixLength() const override; 71*0e209d39SAndroid Build Coastguard Worker 72*0e209d39SAndroid Build Coastguard Worker int32_t getCodePointCount() const override; 73*0e209d39SAndroid Build Coastguard Worker 74*0e209d39SAndroid Build Coastguard Worker bool isStrong() const override; 75*0e209d39SAndroid Build Coastguard Worker 76*0e209d39SAndroid Build Coastguard Worker bool containsField(Field field) const override; 77*0e209d39SAndroid Build Coastguard Worker 78*0e209d39SAndroid Build Coastguard Worker void getParameters(Parameters& output) const override; 79*0e209d39SAndroid Build Coastguard Worker 80*0e209d39SAndroid Build Coastguard Worker bool strictEquals(const Modifier& other) const override; 81*0e209d39SAndroid Build Coastguard Worker 82*0e209d39SAndroid Build Coastguard Worker /** 83*0e209d39SAndroid Build Coastguard Worker * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because 84*0e209d39SAndroid Build Coastguard Worker * FormattedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it. 85*0e209d39SAndroid Build Coastguard Worker * 86*0e209d39SAndroid Build Coastguard Worker * <p> 87*0e209d39SAndroid Build Coastguard Worker * Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices 88*0e209d39SAndroid Build Coastguard Worker * <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start index and after the 89*0e209d39SAndroid Build Coastguard Worker * end index. 90*0e209d39SAndroid Build Coastguard Worker * 91*0e209d39SAndroid Build Coastguard Worker * <p> 92*0e209d39SAndroid Build Coastguard Worker * This is well-defined only for patterns with exactly one argument. 93*0e209d39SAndroid Build Coastguard Worker * 94*0e209d39SAndroid Build Coastguard Worker * @param result 95*0e209d39SAndroid Build Coastguard Worker * The StringBuilder containing the value argument. 96*0e209d39SAndroid Build Coastguard Worker * @param startIndex 97*0e209d39SAndroid Build Coastguard Worker * The left index of the value within the string builder. 98*0e209d39SAndroid Build Coastguard Worker * @param endIndex 99*0e209d39SAndroid Build Coastguard Worker * The right index of the value within the string builder. 100*0e209d39SAndroid Build Coastguard Worker * @return The number of characters (UTF-16 code points) that were added to the StringBuilder. 101*0e209d39SAndroid Build Coastguard Worker */ 102*0e209d39SAndroid Build Coastguard Worker int32_t 103*0e209d39SAndroid Build Coastguard Worker formatAsPrefixSuffix(FormattedStringBuilder& result, int32_t startIndex, int32_t endIndex, 104*0e209d39SAndroid Build Coastguard Worker UErrorCode& status) const; 105*0e209d39SAndroid Build Coastguard Worker 106*0e209d39SAndroid Build Coastguard Worker /** 107*0e209d39SAndroid Build Coastguard Worker * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code. 108*0e209d39SAndroid Build Coastguard Worker * I put it here so that the SimpleFormatter uses in FormattedStringBuilder are near each other. 109*0e209d39SAndroid Build Coastguard Worker * 110*0e209d39SAndroid Build Coastguard Worker * <p> 111*0e209d39SAndroid Build Coastguard Worker * Applies the compiled two-argument pattern to the FormattedStringBuilder. 112*0e209d39SAndroid Build Coastguard Worker * 113*0e209d39SAndroid Build Coastguard Worker * <p> 114*0e209d39SAndroid Build Coastguard Worker * This method is optimized for the case where the prefix and suffix are often empty, such as 115*0e209d39SAndroid Build Coastguard Worker * in the range pattern like "{0}-{1}". 116*0e209d39SAndroid Build Coastguard Worker */ 117*0e209d39SAndroid Build Coastguard Worker static int32_t 118*0e209d39SAndroid Build Coastguard Worker formatTwoArgPattern(const SimpleFormatter& compiled, FormattedStringBuilder& result, 119*0e209d39SAndroid Build Coastguard Worker int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength, 120*0e209d39SAndroid Build Coastguard Worker Field field, UErrorCode& status); 121*0e209d39SAndroid Build Coastguard Worker 122*0e209d39SAndroid Build Coastguard Worker private: 123*0e209d39SAndroid Build Coastguard Worker UnicodeString fCompiledPattern; 124*0e209d39SAndroid Build Coastguard Worker Field fField; 125*0e209d39SAndroid Build Coastguard Worker bool fStrong = false; 126*0e209d39SAndroid Build Coastguard Worker int32_t fPrefixLength = 0; 127*0e209d39SAndroid Build Coastguard Worker int32_t fSuffixOffset = -1; 128*0e209d39SAndroid Build Coastguard Worker int32_t fSuffixLength = 0; 129*0e209d39SAndroid Build Coastguard Worker Modifier::Parameters fParameters; 130*0e209d39SAndroid Build Coastguard Worker }; 131*0e209d39SAndroid Build Coastguard Worker 132*0e209d39SAndroid Build Coastguard Worker /** 133*0e209d39SAndroid Build Coastguard Worker * An implementation of {@link Modifier} that allows for multiple types of fields in the same modifier. Constructed 134*0e209d39SAndroid Build Coastguard Worker * based on the contents of two {@link FormattedStringBuilder} instances (one for the prefix, one for the suffix). 135*0e209d39SAndroid Build Coastguard Worker */ 136*0e209d39SAndroid Build Coastguard Worker class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory { 137*0e209d39SAndroid Build Coastguard Worker public: ConstantMultiFieldModifier(const FormattedStringBuilder & prefix,const FormattedStringBuilder & suffix,bool overwrite,bool strong,const Modifier::Parameters parameters)138*0e209d39SAndroid Build Coastguard Worker ConstantMultiFieldModifier( 139*0e209d39SAndroid Build Coastguard Worker const FormattedStringBuilder &prefix, 140*0e209d39SAndroid Build Coastguard Worker const FormattedStringBuilder &suffix, 141*0e209d39SAndroid Build Coastguard Worker bool overwrite, 142*0e209d39SAndroid Build Coastguard Worker bool strong, 143*0e209d39SAndroid Build Coastguard Worker const Modifier::Parameters parameters) 144*0e209d39SAndroid Build Coastguard Worker : fPrefix(prefix), 145*0e209d39SAndroid Build Coastguard Worker fSuffix(suffix), 146*0e209d39SAndroid Build Coastguard Worker fOverwrite(overwrite), 147*0e209d39SAndroid Build Coastguard Worker fStrong(strong), 148*0e209d39SAndroid Build Coastguard Worker fParameters(parameters) {} 149*0e209d39SAndroid Build Coastguard Worker ConstantMultiFieldModifier(const FormattedStringBuilder & prefix,const FormattedStringBuilder & suffix,bool overwrite,bool strong)150*0e209d39SAndroid Build Coastguard Worker ConstantMultiFieldModifier( 151*0e209d39SAndroid Build Coastguard Worker const FormattedStringBuilder &prefix, 152*0e209d39SAndroid Build Coastguard Worker const FormattedStringBuilder &suffix, 153*0e209d39SAndroid Build Coastguard Worker bool overwrite, 154*0e209d39SAndroid Build Coastguard Worker bool strong) 155*0e209d39SAndroid Build Coastguard Worker : fPrefix(prefix), 156*0e209d39SAndroid Build Coastguard Worker fSuffix(suffix), 157*0e209d39SAndroid Build Coastguard Worker fOverwrite(overwrite), 158*0e209d39SAndroid Build Coastguard Worker fStrong(strong) {} 159*0e209d39SAndroid Build Coastguard Worker 160*0e209d39SAndroid Build Coastguard Worker int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, 161*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const override; 162*0e209d39SAndroid Build Coastguard Worker 163*0e209d39SAndroid Build Coastguard Worker int32_t getPrefixLength() const override; 164*0e209d39SAndroid Build Coastguard Worker 165*0e209d39SAndroid Build Coastguard Worker int32_t getCodePointCount() const override; 166*0e209d39SAndroid Build Coastguard Worker 167*0e209d39SAndroid Build Coastguard Worker bool isStrong() const override; 168*0e209d39SAndroid Build Coastguard Worker 169*0e209d39SAndroid Build Coastguard Worker bool containsField(Field field) const override; 170*0e209d39SAndroid Build Coastguard Worker 171*0e209d39SAndroid Build Coastguard Worker void getParameters(Parameters& output) const override; 172*0e209d39SAndroid Build Coastguard Worker 173*0e209d39SAndroid Build Coastguard Worker bool strictEquals(const Modifier& other) const override; 174*0e209d39SAndroid Build Coastguard Worker 175*0e209d39SAndroid Build Coastguard Worker protected: 176*0e209d39SAndroid Build Coastguard Worker // NOTE: In Java, these are stored as array pointers. In C++, the FormattedStringBuilder is stored by 177*0e209d39SAndroid Build Coastguard Worker // value and is treated internally as immutable. 178*0e209d39SAndroid Build Coastguard Worker FormattedStringBuilder fPrefix; 179*0e209d39SAndroid Build Coastguard Worker FormattedStringBuilder fSuffix; 180*0e209d39SAndroid Build Coastguard Worker bool fOverwrite; 181*0e209d39SAndroid Build Coastguard Worker bool fStrong; 182*0e209d39SAndroid Build Coastguard Worker Modifier::Parameters fParameters; 183*0e209d39SAndroid Build Coastguard Worker }; 184*0e209d39SAndroid Build Coastguard Worker 185*0e209d39SAndroid Build Coastguard Worker /** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */ 186*0e209d39SAndroid Build Coastguard Worker class U_I18N_API CurrencySpacingEnabledModifier : public ConstantMultiFieldModifier { 187*0e209d39SAndroid Build Coastguard Worker public: 188*0e209d39SAndroid Build Coastguard Worker /** Safe code path */ 189*0e209d39SAndroid Build Coastguard Worker CurrencySpacingEnabledModifier( 190*0e209d39SAndroid Build Coastguard Worker const FormattedStringBuilder &prefix, 191*0e209d39SAndroid Build Coastguard Worker const FormattedStringBuilder &suffix, 192*0e209d39SAndroid Build Coastguard Worker bool overwrite, 193*0e209d39SAndroid Build Coastguard Worker bool strong, 194*0e209d39SAndroid Build Coastguard Worker const DecimalFormatSymbols &symbols, 195*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 196*0e209d39SAndroid Build Coastguard Worker 197*0e209d39SAndroid Build Coastguard Worker int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, 198*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const override; 199*0e209d39SAndroid Build Coastguard Worker 200*0e209d39SAndroid Build Coastguard Worker /** Unsafe code path */ 201*0e209d39SAndroid Build Coastguard Worker static int32_t 202*0e209d39SAndroid Build Coastguard Worker applyCurrencySpacing(FormattedStringBuilder &output, int32_t prefixStart, int32_t prefixLen, 203*0e209d39SAndroid Build Coastguard Worker int32_t suffixStart, int32_t suffixLen, const DecimalFormatSymbols &symbols, 204*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 205*0e209d39SAndroid Build Coastguard Worker 206*0e209d39SAndroid Build Coastguard Worker private: 207*0e209d39SAndroid Build Coastguard Worker UnicodeSet fAfterPrefixUnicodeSet; 208*0e209d39SAndroid Build Coastguard Worker UnicodeString fAfterPrefixInsert; 209*0e209d39SAndroid Build Coastguard Worker UnicodeSet fBeforeSuffixUnicodeSet; 210*0e209d39SAndroid Build Coastguard Worker UnicodeString fBeforeSuffixInsert; 211*0e209d39SAndroid Build Coastguard Worker 212*0e209d39SAndroid Build Coastguard Worker enum EAffix { 213*0e209d39SAndroid Build Coastguard Worker PREFIX, SUFFIX 214*0e209d39SAndroid Build Coastguard Worker }; 215*0e209d39SAndroid Build Coastguard Worker 216*0e209d39SAndroid Build Coastguard Worker enum EPosition { 217*0e209d39SAndroid Build Coastguard Worker IN_CURRENCY, IN_NUMBER 218*0e209d39SAndroid Build Coastguard Worker }; 219*0e209d39SAndroid Build Coastguard Worker 220*0e209d39SAndroid Build Coastguard Worker /** Unsafe code path */ 221*0e209d39SAndroid Build Coastguard Worker static int32_t applyCurrencySpacingAffix(FormattedStringBuilder &output, int32_t index, EAffix affix, 222*0e209d39SAndroid Build Coastguard Worker const DecimalFormatSymbols &symbols, UErrorCode &status); 223*0e209d39SAndroid Build Coastguard Worker 224*0e209d39SAndroid Build Coastguard Worker static UnicodeSet 225*0e209d39SAndroid Build Coastguard Worker getUnicodeSet(const DecimalFormatSymbols &symbols, EPosition position, EAffix affix, 226*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 227*0e209d39SAndroid Build Coastguard Worker 228*0e209d39SAndroid Build Coastguard Worker static UnicodeString 229*0e209d39SAndroid Build Coastguard Worker getInsertString(const DecimalFormatSymbols &symbols, EAffix affix, UErrorCode &status); 230*0e209d39SAndroid Build Coastguard Worker }; 231*0e209d39SAndroid Build Coastguard Worker 232*0e209d39SAndroid Build Coastguard Worker /** A Modifier that does not do anything. */ 233*0e209d39SAndroid Build Coastguard Worker class U_I18N_API EmptyModifier : public Modifier, public UMemory { 234*0e209d39SAndroid Build Coastguard Worker public: EmptyModifier(bool isStrong)235*0e209d39SAndroid Build Coastguard Worker explicit EmptyModifier(bool isStrong) : fStrong(isStrong) {} 236*0e209d39SAndroid Build Coastguard Worker apply(FormattedStringBuilder & output,int32_t leftIndex,int32_t rightIndex,UErrorCode & status)237*0e209d39SAndroid Build Coastguard Worker int32_t apply(FormattedStringBuilder &output, int32_t leftIndex, int32_t rightIndex, 238*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const override { 239*0e209d39SAndroid Build Coastguard Worker (void)output; 240*0e209d39SAndroid Build Coastguard Worker (void)leftIndex; 241*0e209d39SAndroid Build Coastguard Worker (void)rightIndex; 242*0e209d39SAndroid Build Coastguard Worker (void)status; 243*0e209d39SAndroid Build Coastguard Worker return 0; 244*0e209d39SAndroid Build Coastguard Worker } 245*0e209d39SAndroid Build Coastguard Worker getPrefixLength()246*0e209d39SAndroid Build Coastguard Worker int32_t getPrefixLength() const override { 247*0e209d39SAndroid Build Coastguard Worker return 0; 248*0e209d39SAndroid Build Coastguard Worker } 249*0e209d39SAndroid Build Coastguard Worker getCodePointCount()250*0e209d39SAndroid Build Coastguard Worker int32_t getCodePointCount() const override { 251*0e209d39SAndroid Build Coastguard Worker return 0; 252*0e209d39SAndroid Build Coastguard Worker } 253*0e209d39SAndroid Build Coastguard Worker isStrong()254*0e209d39SAndroid Build Coastguard Worker bool isStrong() const override { 255*0e209d39SAndroid Build Coastguard Worker return fStrong; 256*0e209d39SAndroid Build Coastguard Worker } 257*0e209d39SAndroid Build Coastguard Worker containsField(Field field)258*0e209d39SAndroid Build Coastguard Worker bool containsField(Field field) const override { 259*0e209d39SAndroid Build Coastguard Worker (void)field; 260*0e209d39SAndroid Build Coastguard Worker return false; 261*0e209d39SAndroid Build Coastguard Worker } 262*0e209d39SAndroid Build Coastguard Worker getParameters(Parameters & output)263*0e209d39SAndroid Build Coastguard Worker void getParameters(Parameters& output) const override { 264*0e209d39SAndroid Build Coastguard Worker output.obj = nullptr; 265*0e209d39SAndroid Build Coastguard Worker } 266*0e209d39SAndroid Build Coastguard Worker strictEquals(const Modifier & other)267*0e209d39SAndroid Build Coastguard Worker bool strictEquals(const Modifier& other) const override { 268*0e209d39SAndroid Build Coastguard Worker return other.getCodePointCount() == 0; 269*0e209d39SAndroid Build Coastguard Worker } 270*0e209d39SAndroid Build Coastguard Worker 271*0e209d39SAndroid Build Coastguard Worker private: 272*0e209d39SAndroid Build Coastguard Worker bool fStrong; 273*0e209d39SAndroid Build Coastguard Worker }; 274*0e209d39SAndroid Build Coastguard Worker 275*0e209d39SAndroid Build Coastguard Worker /** An adopting Modifier store that varies by signum but not plural form. */ 276*0e209d39SAndroid Build Coastguard Worker class U_I18N_API AdoptingSignumModifierStore : public UMemory { 277*0e209d39SAndroid Build Coastguard Worker public: 278*0e209d39SAndroid Build Coastguard Worker virtual ~AdoptingSignumModifierStore(); 279*0e209d39SAndroid Build Coastguard Worker 280*0e209d39SAndroid Build Coastguard Worker AdoptingSignumModifierStore() = default; 281*0e209d39SAndroid Build Coastguard Worker 282*0e209d39SAndroid Build Coastguard Worker // No copying! 283*0e209d39SAndroid Build Coastguard Worker AdoptingSignumModifierStore(const AdoptingSignumModifierStore &other) = delete; 284*0e209d39SAndroid Build Coastguard Worker AdoptingSignumModifierStore& operator=(const AdoptingSignumModifierStore& other) = delete; 285*0e209d39SAndroid Build Coastguard Worker 286*0e209d39SAndroid Build Coastguard Worker // Moving is OK AdoptingSignumModifierStore(AdoptingSignumModifierStore && other)287*0e209d39SAndroid Build Coastguard Worker AdoptingSignumModifierStore(AdoptingSignumModifierStore &&other) noexcept { 288*0e209d39SAndroid Build Coastguard Worker *this = std::move(other); 289*0e209d39SAndroid Build Coastguard Worker } 290*0e209d39SAndroid Build Coastguard Worker AdoptingSignumModifierStore& operator=(AdoptingSignumModifierStore&& other) noexcept; 291*0e209d39SAndroid Build Coastguard Worker 292*0e209d39SAndroid Build Coastguard Worker /** Take ownership of the Modifier and slot it in at the given Signum. */ adoptModifier(Signum signum,const Modifier * mod)293*0e209d39SAndroid Build Coastguard Worker void adoptModifier(Signum signum, const Modifier* mod) { 294*0e209d39SAndroid Build Coastguard Worker U_ASSERT(mods[signum] == nullptr); 295*0e209d39SAndroid Build Coastguard Worker mods[signum] = mod; 296*0e209d39SAndroid Build Coastguard Worker } 297*0e209d39SAndroid Build Coastguard Worker 298*0e209d39SAndroid Build Coastguard Worker inline const Modifier*& operator[](Signum signum) { 299*0e209d39SAndroid Build Coastguard Worker return mods[signum]; 300*0e209d39SAndroid Build Coastguard Worker } 301*0e209d39SAndroid Build Coastguard Worker inline Modifier const* operator[](Signum signum) const { 302*0e209d39SAndroid Build Coastguard Worker return mods[signum]; 303*0e209d39SAndroid Build Coastguard Worker } 304*0e209d39SAndroid Build Coastguard Worker 305*0e209d39SAndroid Build Coastguard Worker private: 306*0e209d39SAndroid Build Coastguard Worker const Modifier* mods[SIGNUM_COUNT] = {}; 307*0e209d39SAndroid Build Coastguard Worker }; 308*0e209d39SAndroid Build Coastguard Worker 309*0e209d39SAndroid Build Coastguard Worker /** 310*0e209d39SAndroid Build Coastguard Worker * This implementation of ModifierStore adopts Modifier pointers. 311*0e209d39SAndroid Build Coastguard Worker */ 312*0e209d39SAndroid Build Coastguard Worker class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory { 313*0e209d39SAndroid Build Coastguard Worker public: 314*0e209d39SAndroid Build Coastguard Worker static constexpr StandardPlural::Form DEFAULT_STANDARD_PLURAL = StandardPlural::OTHER; 315*0e209d39SAndroid Build Coastguard Worker 316*0e209d39SAndroid Build Coastguard Worker AdoptingModifierStore() = default; 317*0e209d39SAndroid Build Coastguard Worker 318*0e209d39SAndroid Build Coastguard Worker // No copying! 319*0e209d39SAndroid Build Coastguard Worker AdoptingModifierStore(const AdoptingModifierStore &other) = delete; 320*0e209d39SAndroid Build Coastguard Worker 321*0e209d39SAndroid Build Coastguard Worker // Moving is OK 322*0e209d39SAndroid Build Coastguard Worker AdoptingModifierStore(AdoptingModifierStore &&other) = default; 323*0e209d39SAndroid Build Coastguard Worker 324*0e209d39SAndroid Build Coastguard Worker /** Sets the modifiers for a specific plural form. */ adoptSignumModifierStore(StandardPlural::Form plural,AdoptingSignumModifierStore other)325*0e209d39SAndroid Build Coastguard Worker void adoptSignumModifierStore(StandardPlural::Form plural, AdoptingSignumModifierStore other) { 326*0e209d39SAndroid Build Coastguard Worker mods[plural] = std::move(other); 327*0e209d39SAndroid Build Coastguard Worker } 328*0e209d39SAndroid Build Coastguard Worker 329*0e209d39SAndroid Build Coastguard Worker /** Sets the modifiers for the default plural form. */ adoptSignumModifierStoreNoPlural(AdoptingSignumModifierStore other)330*0e209d39SAndroid Build Coastguard Worker void adoptSignumModifierStoreNoPlural(AdoptingSignumModifierStore other) { 331*0e209d39SAndroid Build Coastguard Worker mods[DEFAULT_STANDARD_PLURAL] = std::move(other); 332*0e209d39SAndroid Build Coastguard Worker } 333*0e209d39SAndroid Build Coastguard Worker 334*0e209d39SAndroid Build Coastguard Worker /** Returns a reference to the modifier; no ownership change. */ getModifier(Signum signum,StandardPlural::Form plural)335*0e209d39SAndroid Build Coastguard Worker const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const override { 336*0e209d39SAndroid Build Coastguard Worker const Modifier* modifier = mods[plural][signum]; 337*0e209d39SAndroid Build Coastguard Worker if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) { 338*0e209d39SAndroid Build Coastguard Worker modifier = mods[DEFAULT_STANDARD_PLURAL][signum]; 339*0e209d39SAndroid Build Coastguard Worker } 340*0e209d39SAndroid Build Coastguard Worker return modifier; 341*0e209d39SAndroid Build Coastguard Worker } 342*0e209d39SAndroid Build Coastguard Worker 343*0e209d39SAndroid Build Coastguard Worker /** Returns a reference to the modifier; no ownership change. */ getModifierWithoutPlural(Signum signum)344*0e209d39SAndroid Build Coastguard Worker const Modifier *getModifierWithoutPlural(Signum signum) const { 345*0e209d39SAndroid Build Coastguard Worker return mods[DEFAULT_STANDARD_PLURAL][signum]; 346*0e209d39SAndroid Build Coastguard Worker } 347*0e209d39SAndroid Build Coastguard Worker 348*0e209d39SAndroid Build Coastguard Worker private: 349*0e209d39SAndroid Build Coastguard Worker // NOTE: mods is zero-initialized (to nullptr) 350*0e209d39SAndroid Build Coastguard Worker AdoptingSignumModifierStore mods[StandardPlural::COUNT] = {}; 351*0e209d39SAndroid Build Coastguard Worker }; 352*0e209d39SAndroid Build Coastguard Worker 353*0e209d39SAndroid Build Coastguard Worker } // namespace number::impl 354*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END 355*0e209d39SAndroid Build Coastguard Worker 356*0e209d39SAndroid Build Coastguard Worker 357*0e209d39SAndroid Build Coastguard Worker #endif //__NUMBER_MODIFIERS_H__ 358*0e209d39SAndroid Build Coastguard Worker 359*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */ 360