]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/number_modifiers.cpp
ICU-64232.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / number_modifiers.cpp
index 4385499b54f603fdb6d686de6fff9fbbf0e93023..1fcbe7b9b79301de84a0bd9fc1a6816b19105b95 100644 (file)
@@ -53,6 +53,21 @@ void U_CALLCONV initDefaultCurrencySpacing(UErrorCode &status) {
 
 Modifier::~Modifier() = default;
 
+Modifier::Parameters::Parameters()
+        : obj(nullptr) {}
+
+Modifier::Parameters::Parameters(
+    const ModifierStore* _obj, int8_t _signum, StandardPlural::Form _plural)
+        : obj(_obj), signum(_signum), plural(_plural) {}
+
+ModifierStore::~ModifierStore() = default;
+
+AdoptingModifierStore::~AdoptingModifierStore()  {
+    for (const Modifier *mod : mods) {
+        delete mod;
+    }
+}
+
 
 int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
                                      UErrorCode &status) const {
@@ -62,13 +77,11 @@ int32_t ConstantAffixModifier::apply(NumberStringBuilder &output, int leftIndex,
     return length;
 }
 
-int32_t ConstantAffixModifier::getPrefixLength(UErrorCode &status) const {
-    (void)status;
+int32_t ConstantAffixModifier::getPrefixLength() const {
     return fPrefix.length();
 }
 
-int32_t ConstantAffixModifier::getCodePointCount(UErrorCode &status) const {
-    (void)status;
+int32_t ConstantAffixModifier::getCodePointCount() const {
     return fPrefix.countChar32() + fSuffix.countChar32();
 }
 
@@ -76,8 +89,37 @@ bool ConstantAffixModifier::isStrong() const {
     return fStrong;
 }
 
+bool ConstantAffixModifier::containsField(UNumberFormatFields field) const {
+    (void)field;
+    // This method is not currently used.
+    UPRV_UNREACHABLE;
+}
+
+void ConstantAffixModifier::getParameters(Parameters& output) const {
+    (void)output;
+    // This method is not currently used.
+    UPRV_UNREACHABLE;
+}
+
+bool ConstantAffixModifier::semanticallyEquivalent(const Modifier& other) const {
+    auto* _other = dynamic_cast<const ConstantAffixModifier*>(&other);
+    if (_other == nullptr) {
+        return false;
+    }
+    return fPrefix == _other->fPrefix
+        && fSuffix == _other->fSuffix
+        && fField == _other->fField
+        && fStrong == _other->fStrong;
+}
+
+
 SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong)
-        : fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong) {
+        : SimpleModifier(simpleFormatter, field, strong, {}) {}
+
+SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field field, bool strong,
+                               const Modifier::Parameters parameters)
+        : fCompiledPattern(simpleFormatter.compiledPattern), fField(field), fStrong(strong),
+          fParameters(parameters) {
     int32_t argLimit = SimpleFormatter::getArgumentLimit(
             fCompiledPattern.getBuffer(), fCompiledPattern.length());
     if (argLimit == 0) {
@@ -90,15 +132,19 @@ SimpleModifier::SimpleModifier(const SimpleFormatter &simpleFormatter, Field fie
     } else {
         U_ASSERT(argLimit == 1);
         if (fCompiledPattern.charAt(1) != 0) {
+            // Found prefix
             fPrefixLength = fCompiledPattern.charAt(1) - ARG_NUM_LIMIT;
             fSuffixOffset = 3 + fPrefixLength;
         } else {
+            // No prefix
             fPrefixLength = 0;
             fSuffixOffset = 2;
         }
         if (3 + fPrefixLength < fCompiledPattern.length()) {
+            // Found suffix
             fSuffixLength = fCompiledPattern.charAt(fSuffixOffset) - ARG_NUM_LIMIT;
         } else {
+            // No suffix
             fSuffixLength = 0;
         }
     }
@@ -110,16 +156,14 @@ SimpleModifier::SimpleModifier()
 
 int32_t SimpleModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
                               UErrorCode &status) const {
-    return formatAsPrefixSuffix(output, leftIndex, rightIndex, fField, status);
+    return formatAsPrefixSuffix(output, leftIndex, rightIndex, status);
 }
 
-int32_t SimpleModifier::getPrefixLength(UErrorCode &status) const {
-    (void)status;
+int32_t SimpleModifier::getPrefixLength() const {
     return fPrefixLength;
 }
 
-int32_t SimpleModifier::getCodePointCount(UErrorCode &status) const {
-    (void)status;
+int32_t SimpleModifier::getCodePointCount() const {
     int32_t count = 0;
     if (fPrefixLength > 0) {
         count += fCompiledPattern.countChar32(2, fPrefixLength);
@@ -134,15 +178,39 @@ bool SimpleModifier::isStrong() const {
     return fStrong;
 }
 
+bool SimpleModifier::containsField(UNumberFormatFields field) const {
+    (void)field;
+    // This method is not currently used.
+    UPRV_UNREACHABLE;
+}
+
+void SimpleModifier::getParameters(Parameters& output) const {
+    output = fParameters;
+}
+
+bool SimpleModifier::semanticallyEquivalent(const Modifier& other) const {
+    auto* _other = dynamic_cast<const SimpleModifier*>(&other);
+    if (_other == nullptr) {
+        return false;
+    }
+    if (fParameters.obj != nullptr) {
+        return fParameters.obj == _other->fParameters.obj;
+    }
+    return fCompiledPattern == _other->fCompiledPattern
+        && fField == _other->fField
+        && fStrong == _other->fStrong;
+}
+
+
 int32_t
 SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startIndex, int32_t endIndex,
-                                     Field field, UErrorCode &status) const {
-    if (fSuffixOffset == -1) {
+                                     UErrorCode &status) const {
+    if (fSuffixOffset == -1 && fPrefixLength + fSuffixLength > 0) {
         // There is no argument for the inner number; overwrite the entire segment with our string.
-        return result.splice(startIndex, endIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
+        return result.splice(startIndex, endIndex, fCompiledPattern, 2, 2 + fPrefixLength, fField, status);
     } else {
         if (fPrefixLength > 0) {
-            result.insert(startIndex, fCompiledPattern, 2, 2 + fPrefixLength, field, status);
+            result.insert(startIndex, fCompiledPattern, 2, 2 + fPrefixLength, fField, status);
         }
         if (fSuffixLength > 0) {
             result.insert(
@@ -150,13 +218,72 @@ SimpleModifier::formatAsPrefixSuffix(NumberStringBuilder &result, int32_t startI
                     fCompiledPattern,
                     1 + fSuffixOffset,
                     1 + fSuffixOffset + fSuffixLength,
-                    field,
+                    fField,
                     status);
         }
         return fPrefixLength + fSuffixLength;
     }
 }
 
+
+int32_t
+SimpleModifier::formatTwoArgPattern(const SimpleFormatter& compiled, NumberStringBuilder& result,
+                                    int32_t index, int32_t* outPrefixLength, int32_t* outSuffixLength,
+                                    Field field, UErrorCode& status) {
+    const UnicodeString& compiledPattern = compiled.compiledPattern;
+    int32_t argLimit = SimpleFormatter::getArgumentLimit(
+            compiledPattern.getBuffer(), compiledPattern.length());
+    if (argLimit != 2) {
+        status = U_INTERNAL_PROGRAM_ERROR;
+        return 0;
+    }
+    int32_t offset = 1; // offset into compiledPattern
+    int32_t length = 0; // chars added to result
+
+    int32_t prefixLength = compiledPattern.charAt(offset);
+    offset++;
+    if (prefixLength < ARG_NUM_LIMIT) {
+        // No prefix
+        prefixLength = 0;
+    } else {
+        prefixLength -= ARG_NUM_LIMIT;
+        result.insert(index + length, compiledPattern, offset, offset + prefixLength, field, status);
+        offset += prefixLength;
+        length += prefixLength;
+        offset++;
+    }
+
+    int32_t infixLength = compiledPattern.charAt(offset);
+    offset++;
+    if (infixLength < ARG_NUM_LIMIT) {
+        // No infix
+        infixLength = 0;
+    } else {
+        infixLength -= ARG_NUM_LIMIT;
+        result.insert(index + length, compiledPattern, offset, offset + infixLength, field, status);
+        offset += infixLength;
+        length += infixLength;
+        offset++;
+    }
+
+    int32_t suffixLength;
+    if (offset == compiledPattern.length()) {
+        // No suffix
+        suffixLength = 0;
+    } else {
+        suffixLength = compiledPattern.charAt(offset) -  ARG_NUM_LIMIT;
+        offset++;
+        result.insert(index + length, compiledPattern, offset, offset + suffixLength, field, status);
+        length += suffixLength;
+    }
+
+    *outPrefixLength = prefixLength;
+    *outSuffixLength = suffixLength;
+
+    return length;
+}
+
+
 int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftIndex, int rightIndex,
                                           UErrorCode &status) const {
     int32_t length = output.insert(leftIndex, fPrefix, status);
@@ -171,13 +298,11 @@ int32_t ConstantMultiFieldModifier::apply(NumberStringBuilder &output, int leftI
     return length;
 }
 
-int32_t ConstantMultiFieldModifier::getPrefixLength(UErrorCode &status) const {
-    (void)status;
+int32_t ConstantMultiFieldModifier::getPrefixLength() const {
     return fPrefix.length();
 }
 
-int32_t ConstantMultiFieldModifier::getCodePointCount(UErrorCode &status) const {
-    (void)status;
+int32_t ConstantMultiFieldModifier::getCodePointCount() const {
     return fPrefix.codePointCount() + fSuffix.codePointCount();
 }
 
@@ -185,6 +310,29 @@ bool ConstantMultiFieldModifier::isStrong() const {
     return fStrong;
 }
 
+bool ConstantMultiFieldModifier::containsField(UNumberFormatFields field) const {
+    return fPrefix.containsField(field) || fSuffix.containsField(field);
+}
+
+void ConstantMultiFieldModifier::getParameters(Parameters& output) const {
+    output = fParameters;
+}
+
+bool ConstantMultiFieldModifier::semanticallyEquivalent(const Modifier& other) const {
+    auto* _other = dynamic_cast<const ConstantMultiFieldModifier*>(&other);
+    if (_other == nullptr) {
+        return false;
+    }
+    if (fParameters.obj != nullptr) {
+        return fParameters.obj == _other->fParameters.obj;
+    }
+    return fPrefix.contentEquals(_other->fPrefix)
+        && fSuffix.contentEquals(_other->fSuffix)
+        && fOverwrite == _other->fOverwrite
+        && fStrong == _other->fStrong;
+}
+
+
 CurrencySpacingEnabledModifier::CurrencySpacingEnabledModifier(const NumberStringBuilder &prefix,
                                                                const NumberStringBuilder &suffix,
                                                                bool overwrite,