Exemplo n.º 1
0
void CompactHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
                                     UErrorCode &status) const {
    parent->processQuantity(quantity, micros, status);
    if (U_FAILURE(status)) { return; }

    // Treat zero as if it had magnitude 0
    int32_t magnitude;
    if (quantity.isZero()) {
        magnitude = 0;
        micros.rounder.apply(quantity, status);
    } else {
        // TODO: Revisit chooseMultiplierAndApply
        int32_t multiplier = micros.rounder.chooseMultiplierAndApply(quantity, data, status);
        magnitude = quantity.isZero() ? 0 : quantity.getMagnitude();
        magnitude -= multiplier;
    }

    StandardPlural::Form plural = utils::getStandardPlural(rules, quantity);
    const UChar *patternString = data.getPattern(magnitude, plural);
    if (patternString == nullptr) {
        // Use the default (non-compact) modifier.
        // No need to take any action.
    } else if (safe) {
        // Safe code path.
        // Java uses a hash set here for O(1) lookup.  C++ uses a linear search.
        // TODO: Benchmark this and maybe change to a binary search or hash table.
        int32_t i = 0;
        for (; i < precomputedModsLength; i++) {
            const CompactModInfo &info = precomputedMods[i];
            if (u_strcmp(patternString, info.patternString) == 0) {
                info.mod->applyToMicros(micros, quantity);
                break;
            }
        }
        // It should be guaranteed that we found the entry.
        U_ASSERT(i < precomputedModsLength);
    } else {
        // Unsafe code path.
        // Overwrite the PatternInfo in the existing modMiddle.
        // C++ Note: Use unsafePatternInfo for proper lifecycle.
        ParsedPatternInfo &patternInfo = const_cast<CompactHandler *>(this)->unsafePatternInfo;
        PatternParser::parseToPatternInfo(UnicodeString(patternString), patternInfo, status);
        static_cast<MutablePatternModifier*>(const_cast<Modifier*>(micros.modMiddle))
            ->setPatternInfo(&patternInfo);
    }

    // We already performed rounding. Do not perform it again.
    micros.rounder = RoundingImpl::passThrough();
}
Exemplo n.º 2
0
void ScientificHandler::processQuantity(DecimalQuantity &quantity, MicroProps &micros,
                                        UErrorCode &status) const {
    fParent->processQuantity(quantity, micros, status);
    if (U_FAILURE(status)) { return; }

    // Treat zero as if it had magnitude 0
    int32_t exponent;
    if (quantity.isZero()) {
        if (fSettings.fRequireMinInt && micros.rounder.isSignificantDigits()) {
            // Show "00.000E0" on pattern "00.000E0"
            micros.rounder.apply(quantity, fSettings.fEngineeringInterval, status);
            exponent = 0;
        } else {
            micros.rounder.apply(quantity, status);
            exponent = 0;
        }
    } else {
        exponent = -micros.rounder.chooseMultiplierAndApply(quantity, *this, status);
    }

    // Use MicroProps's helper ScientificModifier and save it as the modInner.
    ScientificModifier &mod = micros.helpers.scientificModifier;
    mod.set(exponent, this);
    micros.modInner = &mod;

    // We already performed rounding. Do not perform it again.
    micros.rounder = RoundingImpl::passThrough();
}