int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
- int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE;
+ int32_t getPrefixLength() const U_OVERRIDE;
- int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE;
+ int32_t getCodePointCount() const U_OVERRIDE;
bool isStrong() const U_OVERRIDE;
+ bool containsField(UNumberFormatFields field) const U_OVERRIDE;
+
+ void getParameters(Parameters& output) const U_OVERRIDE;
+
+ bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
+
private:
UnicodeString fPrefix;
UnicodeString fSuffix;
public:
SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong);
+ SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong,
+ const Modifier::Parameters parameters);
+
// Default constructor for LongNameHandler.h
SimpleModifier();
int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
- int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE;
+ int32_t getPrefixLength() const U_OVERRIDE;
- int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE;
+ int32_t getCodePointCount() const U_OVERRIDE;
bool isStrong() const U_OVERRIDE;
+ bool containsField(UNumberFormatFields field) const U_OVERRIDE;
+
+ void getParameters(Parameters& output) const U_OVERRIDE;
+
+ bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
+
/**
* TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because
- * DoubleSidedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
+ * NumberStringBuilder is an internal class and SimpleFormatterImpl feels like it should not depend on it.
*
* <p>
* Formats a value that is already stored inside the StringBuilder <code>result</code> between the indices
* @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
*/
int32_t
- formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex, Field field,
- UErrorCode &status) const;
+ formatAsPrefixSuffix(NumberStringBuilder& result, int32_t startIndex, int32_t endIndex,
+ UErrorCode& status) const;
+
+ /**
+ * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code.
+ * I put it here so that the SimpleFormatter uses in NumberStringBuilder are near each other.
+ *
+ * <p>
+ * Applies the compiled two-argument pattern to the NumberStringBuilder.
+ *
+ * <p>
+ * This method is optimized for the case where the prefix and suffix are often empty, such as
+ * in the range pattern like "{0}-{1}".
+ */
+ static int32_t
+ formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result,
+ int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength,
+ Field field, UErrorCode& status);
private:
UnicodeString fCompiledPattern;
Field fField;
- bool fStrong;
- int32_t fPrefixLength;
- int32_t fSuffixOffset;
- int32_t fSuffixLength;
+ bool fStrong = false;
+ int32_t fPrefixLength = 0;
+ int32_t fSuffixOffset = -1;
+ int32_t fSuffixLength = 0;
+ Modifier::Parameters fParameters;
};
/**
*/
class U_I18N_API ConstantMultiFieldModifier : public Modifier, public UMemory {
public:
+ ConstantMultiFieldModifier(
+ const NumberStringBuilder &prefix,
+ const NumberStringBuilder &suffix,
+ bool overwrite,
+ bool strong,
+ const Modifier::Parameters parameters)
+ : fPrefix(prefix),
+ fSuffix(suffix),
+ fOverwrite(overwrite),
+ fStrong(strong),
+ fParameters(parameters) {}
+
ConstantMultiFieldModifier(
const NumberStringBuilder &prefix,
const NumberStringBuilder &suffix,
int32_t apply(NumberStringBuilder &output, int32_t leftIndex, int32_t rightIndex,
UErrorCode &status) const U_OVERRIDE;
- int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE;
+ int32_t getPrefixLength() const U_OVERRIDE;
- int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE;
+ int32_t getCodePointCount() const U_OVERRIDE;
bool isStrong() const U_OVERRIDE;
+ bool containsField(UNumberFormatFields field) const U_OVERRIDE;
+
+ void getParameters(Parameters& output) const U_OVERRIDE;
+
+ bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE;
+
protected:
// NOTE: In Java, these are stored as array pointers. In C++, the NumberStringBuilder is stored by
// value and is treated internally as immutable.
NumberStringBuilder fSuffix;
bool fOverwrite;
bool fStrong;
+ Modifier::Parameters fParameters;
};
/** Identical to {@link ConstantMultiFieldModifier}, but supports currency spacing. */
return 0;
}
- int32_t getPrefixLength(UErrorCode &status) const U_OVERRIDE {
- (void)status;
+ int32_t getPrefixLength() const U_OVERRIDE {
return 0;
}
- int32_t getCodePointCount(UErrorCode &status) const U_OVERRIDE {
- (void)status;
+ int32_t getCodePointCount() const U_OVERRIDE {
return 0;
}
return fStrong;
}
+ bool containsField(UNumberFormatFields field) const U_OVERRIDE {
+ (void)field;
+ return false;
+ }
+
+ void getParameters(Parameters& output) const U_OVERRIDE {
+ output.obj = nullptr;
+ }
+
+ bool semanticallyEquivalent(const Modifier& other) const U_OVERRIDE {
+ return other.getCodePointCount() == 0;
+ }
+
private:
bool fStrong;
};
/**
- * A ParameterizedModifier by itself is NOT a Modifier. Rather, it wraps a data structure containing two or more
- * Modifiers and returns the modifier appropriate for the current situation.
+ * This implementation of ModifierStore adopts Modifer pointers.
*/
-class U_I18N_API ParameterizedModifier : public UMemory {
+class U_I18N_API AdoptingModifierStore : public ModifierStore, public UMemory {
public:
- // NOTE: mods is zero-initialized (to nullptr)
- ParameterizedModifier() : mods() {
- }
+ virtual ~AdoptingModifierStore();
- // No copying!
- ParameterizedModifier(const ParameterizedModifier &other) = delete;
+ static constexpr StandardPlural::Form DEFAULT_STANDARD_PLURAL = StandardPlural::OTHER;
- ~ParameterizedModifier() {
- for (const Modifier *mod : mods) {
- delete mod;
- }
- }
+ AdoptingModifierStore() = default;
- void adoptPositiveNegativeModifiers(
- const Modifier *positive, const Modifier *zero, const Modifier *negative) {
- mods[2] = positive;
- mods[1] = zero;
- mods[0] = negative;
- }
+ // No copying!
+ AdoptingModifierStore(const AdoptingModifierStore &other) = delete;
- /** The modifier is ADOPTED. */
- void adoptSignPluralModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) {
+ /**
+ * Sets the Modifier with the specified signum and plural form.
+ */
+ void adoptModifier(int8_t signum, StandardPlural::Form plural, const Modifier *mod) {
+ U_ASSERT(mods[getModIndex(signum, plural)] == nullptr);
mods[getModIndex(signum, plural)] = mod;
}
+ /**
+ * Sets the Modifier with the specified signum.
+ * The modifier will apply to all plural forms.
+ */
+ void adoptModifierWithoutPlural(int8_t signum, const Modifier *mod) {
+ U_ASSERT(mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] == nullptr);
+ mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)] = mod;
+ }
+
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifier(int8_t signum) const {
- return mods[signum + 1];
+ const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const U_OVERRIDE {
+ const Modifier* modifier = mods[getModIndex(signum, plural)];
+ if (modifier == nullptr && plural != DEFAULT_STANDARD_PLURAL) {
+ modifier = mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
+ }
+ return modifier;
}
/** Returns a reference to the modifier; no ownership change. */
- const Modifier *getModifier(int8_t signum, StandardPlural::Form plural) const {
- return mods[getModIndex(signum, plural)];
+ const Modifier *getModifierWithoutPlural(int8_t signum) const {
+ return mods[getModIndex(signum, DEFAULT_STANDARD_PLURAL)];
}
private:
- const Modifier *mods[3 * StandardPlural::COUNT];
+ // NOTE: mods is zero-initialized (to nullptr)
+ const Modifier *mods[3 * StandardPlural::COUNT] = {};
inline static int32_t getModIndex(int8_t signum, StandardPlural::Form plural) {
+ U_ASSERT(signum >= -1 && signum <= 1);
+ U_ASSERT(plural >= 0 && plural < StandardPlural::COUNT);
return static_cast<int32_t>(plural) * 3 + (signum + 1);
}
};