// Allow implicit conversion from char16_t* to UnicodeString for this file: // Helpful in toString methods and elsewhere. #define UNISTR_FROM_STRING_EXPLICIT
// Helper function for 2-dimensional switch statement
constexpr int8_t identity2d(UNumberRangeIdentityFallback a, UNumberRangeIdentityResult b) { returnstatic_cast<int8_t>(a) | (static_cast<int8_t>(b) << 4);
}
struct NumberRangeData {
SimpleFormatter rangePattern; // Note: approximatelyPattern is unused since ICU 69. // SimpleFormatter approximatelyPattern;
};
class NumberRangeDataSink : public ResourceSink { public:
NumberRangeDataSink(NumberRangeData& data) : fData(data) {}
void put(constchar* key, ResourceValue& value, UBool /*noFallback*/, UErrorCode& status) override {
ResourceTable miscTable = value.getTable(status); if (U_FAILURE(status)) { return; } for (int i = 0; miscTable.getKeyAndValue(i, key, value); i++) { if (uprv_strcmp(key, "range") == 0) { if (hasRangeData()) { continue; // have already seen this pattern
}
fData.rangePattern = {value.getUnicodeString(status), status};
} /* // Note: approximatelyPattern is unused since ICU 69. else if (uprv_strcmp(key, "approximately") == 0) { if (hasApproxData()) { continue; // have already seen this pattern } fData.approximatelyPattern = {value.getUnicodeString(status), status}; }
*/
}
}
UErrorCode localStatus = U_ZERO_ERROR;
ures_getAllItemsWithFallback(rb.getAlias(), dataPath.data(), sink, localStatus); if (U_FAILURE(localStatus) && localStatus != U_MISSING_RESOURCE_ERROR) {
status = localStatus; return;
}
// Fall back to latn if necessary if (!sink.isComplete()) {
ures_getAllItemsWithFallback(rb.getAlias(), "NumberElements/latn/miscPatterns", sink, status);
}
// If any of the affixes are different, an identity is not possible // and we must use formatRange(). // TODO: Write this as MicroProps operator==() ? // TODO: Avoid the redundancy of these equality operations with the // ones in formatRange? if (!micros1.modInner->semanticallyEquivalent(*micros2.modInner)
|| !micros1.modMiddle->semanticallyEquivalent(*micros2.modMiddle)
|| !micros1.modOuter->semanticallyEquivalent(*micros2.modOuter)) {
formatRange(data, micros1, micros2, status);
data.identityResult = UNUM_IDENTITY_RESULT_NOT_EQUAL; return;
}
switch (identity2d(fIdentityFallback, data.identityResult)) { case identity2d(UNUM_IDENTITY_FALLBACK_RANGE,
UNUM_IDENTITY_RESULT_NOT_EQUAL): case identity2d(UNUM_IDENTITY_FALLBACK_RANGE,
UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING): case identity2d(UNUM_IDENTITY_FALLBACK_RANGE,
UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING): case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
UNUM_IDENTITY_RESULT_NOT_EQUAL): case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE,
UNUM_IDENTITY_RESULT_NOT_EQUAL): case identity2d(UNUM_IDENTITY_FALLBACK_SINGLE_VALUE,
UNUM_IDENTITY_RESULT_NOT_EQUAL):
formatRange(data, micros1, micros2, status); break;
case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING): case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING): case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE,
UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING):
formatApproximately(data, micros1, micros2, status); break;
case identity2d(UNUM_IDENTITY_FALLBACK_APPROXIMATELY_OR_SINGLE_VALUE,
UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING): case identity2d(UNUM_IDENTITY_FALLBACK_SINGLE_VALUE,
UNUM_IDENTITY_RESULT_EQUAL_AFTER_ROUNDING): case identity2d(UNUM_IDENTITY_FALLBACK_SINGLE_VALUE,
UNUM_IDENTITY_RESULT_EQUAL_BEFORE_ROUNDING):
formatSingleValue(data, micros1, micros2, status); break;
// modInner is always notation (scientific); collapsable in ALL. // modOuter is always units; collapsable in ALL, AUTO, and UNIT. // modMiddle could be either; collapsable in ALL and sometimes AUTO and UNIT. // Never collapse an outer mod but not an inner mod. bool collapseOuter, collapseMiddle, collapseInner; switch (fCollapse) { case UNUM_RANGE_COLLAPSE_ALL: case UNUM_RANGE_COLLAPSE_AUTO: case UNUM_RANGE_COLLAPSE_UNIT:
{ // OUTER MODIFIER
collapseOuter = micros1.modOuter->semanticallyEquivalent(*micros2.modOuter);
if (!collapseOuter) { // Never collapse inner mods if outer mods are not collapsable
collapseMiddle = false;
collapseInner = false; break;
}
if (!collapseMiddle) { // Never collapse inner mods if outer mods are not collapsable
collapseInner = false; break;
}
// MIDDLE MODIFIER HEURISTICS // (could disable collapsing of the middle modifier) // The modifiers are equal by this point, so we can look at just one of them. const Modifier* mm = micros1.modMiddle; if (fCollapse == UNUM_RANGE_COLLAPSE_UNIT) { // Only collapse if the modifier is a unit. // TODO: Make a better way to check for a unit? // TODO: Handle case where the modifier has both notation and unit (compact currency)? if (!mm->containsField({UFIELD_CATEGORY_NUMBER, UNUM_CURRENCY_FIELD})
&& !mm->containsField({UFIELD_CATEGORY_NUMBER, UNUM_PERCENT_FIELD})) {
collapseMiddle = false;
}
} elseif (fCollapse == UNUM_RANGE_COLLAPSE_AUTO) { // Heuristic as of ICU 63: collapse only if the modifier is more than one code point. if (mm->getCodePointCount() <= 1) {
collapseMiddle = false;
}
}
// Now that all pieces are added, save the span info.
data.appendSpanInfo(UFIELD_CATEGORY_NUMBER_RANGE_SPAN, 0, UPRV_INDEX_0, length1, status);
data.appendSpanInfo(UFIELD_CATEGORY_NUMBER_RANGE_SPAN, 1, UPRV_INDEX_2, length2, status);
}
const Modifier&
NumberRangeFormatterImpl::resolveModifierPlurals(const Modifier& first, const Modifier& second) const {
Modifier::Parameters parameters;
first.getParameters(parameters); if (parameters.obj == nullptr) { // No plural form; return a fallback (e.g., the first) return first;
}
StandardPlural::Form firstPlural = parameters.plural;
second.getParameters(parameters); if (parameters.obj == nullptr) { // No plural form; return a fallback (e.g., the first) return first;
}
StandardPlural::Form secondPlural = parameters.plural;
// Get the required plural form from data
StandardPlural::Form resultPlural = fPluralRanges.resolve(firstPlural, secondPlural);
// Get and return the new Modifier const Modifier* mod = parameters.obj->getModifier(parameters.signum, resultPlural);
U_ASSERT(mod != nullptr); return *mod;
}
#endif/* #if !UCONFIG_NO_FORMATTING */
Messung V0.5
¤ Dauer der Verarbeitung: 0.34 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.