/** *Methodforuseby`ures_getAllItemsWithFallback`.Addstheunit *conversionratesthatarefoundin`value`totheoutputvector. * *@paramsourceThisstringmustbe"convertUnits":theresourcethatthis *classsupportsreading. *@paramvalueThe"convertUnits"resource,containingunitconversionrate *information. *@paramnoFallbackIgnored. *@paramstatusThestandardICUerrorcodeoutputparameter.
*/ void put(constchar *source, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) override { if (U_FAILURE(status)) { return; } if (uprv_strcmp(source, "convertUnits") != 0) { // This is very strict, however it is the cheapest way to be sure // that with `value`, we're looking at the convertUnits table.
status = U_ILLEGAL_ARGUMENT_ERROR; return;
}
ResourceTable conversionRateTable = value.getTable(status); constchar *srcUnit; // We're reusing `value`, which seems to be a common pattern: for (int32_t unit = 0; conversionRateTable.getKeyAndValue(unit, srcUnit, value); unit++) {
ResourceTable unitTable = value.getTable(status); constchar *key;
UnicodeString baseUnit = ICU_Utility::makeBogusString();
UnicodeString factor = ICU_Utility::makeBogusString();
UnicodeString offset = ICU_Utility::makeBogusString();
UnicodeString special = ICU_Utility::makeBogusString();
UnicodeString systems = ICU_Utility::makeBogusString(); for (int32_t i = 0; unitTable.getKeyAndValue(i, key, value); i++) { if (uprv_strcmp(key, "target") == 0) {
baseUnit = value.getUnicodeString(status);
} elseif (uprv_strcmp(key, "factor") == 0) {
factor = value.getUnicodeString(status);
} elseif (uprv_strcmp(key, "offset") == 0) {
offset = value.getUnicodeString(status);
} elseif (uprv_strcmp(key, "special") == 0) {
special = value.getUnicodeString(status); // the name of a special mapping used instead of factor + optional offset.
} elseif (uprv_strcmp(key, "systems") == 0) {
systems = value.getUnicodeString(status);
}
} if (U_FAILURE(status)) { return; } if (baseUnit.isBogus() || (factor.isBogus() && special.isBogus())) { // We could not find a usable conversion rate: bad resource.
status = U_MISSING_RESOURCE_ERROR; return;
}
// We don't have this ConversionRateInfo yet: add it.
ConversionRateInfo *cr = outVector->emplaceBack(); if (!cr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
} else {
cr->sourceUnit = srcUnit; if (cr->sourceUnit.isEmpty() != (*srcUnit == '\0')) {
status = U_MEMORY_ALLOCATION_ERROR;
}
copyInvariantChars(baseUnit, cr->baseUnit, status); if (U_SUCCESS(status) && !factor.isBogus()) {
CharString tmp;
tmp.appendInvariantChars(factor, status);
trimSpaces(tmp, status); if (U_SUCCESS(status)) {
cr->factor = tmp.toStringPiece(); if (cr->factor.isEmpty() != tmp.isEmpty()) {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
} if (!offset.isBogus()) { copyInvariantChars(offset, cr->offset, status); } if (!special.isBogus()) { copyInvariantChars(special, cr->specialMappingName, status); }
copyInvariantChars(systems, cr->systems, status);
}
}
}
/** *Methodforuseby`ures_getAllItemsWithFallback`.Addstheunit *preferencesinfothatarefoundin`value`totheoutputvector. * *@paramsourceThisstringmustbe"unitPreferenceData":theresourcethat *thisclasssupportsreading. *@paramvalueThe"unitPreferenceData"resource,containingunit *preferencesdata. *@paramnoFallbackIgnored. *@paramstatusThestandardICUerrorcodeoutputparameter.Note:ifan *errorisreturned,outPrefsandoutMetadatamaybeinconsistent.
*/ void put(constchar *key, ResourceValue &value, UBool /*noFallback*/, UErrorCode &status) override { if (U_FAILURE(status)) { return; } if (uprv_strcmp(key, "unitPreferenceData") != 0) { // This is very strict, however it is the cheapest way to be sure // that with `value`, we're looking at the convertUnits table.
status = U_ILLEGAL_ARGUMENT_ERROR; return;
} // The unitPreferenceData structure (see data/misc/units.txt) contains a // hierarchy of category/usage/region, within which are a set of // preferences. Hence three for-loops and another loop for the // preferences themselves:
ResourceTable unitPreferenceDataTable = value.getTable(status); constchar *category; for (int32_t i = 0; unitPreferenceDataTable.getKeyAndValue(i, category, value); i++) {
ResourceTable categoryTable = value.getTable(status); constchar *usage; for (int32_t j = 0; categoryTable.getKeyAndValue(j, usage, value); j++) {
ResourceTable regionTable = value.getTable(status); constchar *region; for (int32_t k = 0; regionTable.getKeyAndValue(k, region, value); k++) { // `value` now contains the set of preferences for // category/usage/region.
ResourceArray unitPrefs = value.getArray(status); if (U_FAILURE(status)) { return; }
int32_t prefLen = unitPrefs.getSize();
// Update metadata for this set of preferences.
UnitPreferenceMetadata *meta = metadata->emplaceBack(
category, usage, region, preferences->length(), prefLen, status); if (!meta) {
status = U_MEMORY_ALLOCATION_ERROR; return;
} if (U_FAILURE(status)) { return; } if (metadata->length() > 1) { // Verify that unit preferences are sorted and // without duplicates. if (!(*(*metadata)[metadata->length() - 2] <
*(*metadata)[metadata->length() - 1])) {
status = U_INVALID_FORMAT_ERROR; return;
}
}
// TODO: remove this once all the categories are allowed. // WARNING: when this is removed please make sure to keep the "fahrenhe" => "fahrenheit" mapping
UErrorCode internalMuStatus = U_ZERO_ERROR; if (category.compare("temperature") == 0) {
CharString localeUnitCharString = getKeyWordValue(locale, "mu", internalMuStatus); if (U_SUCCESS(internalMuStatus)) { // The value for -u-mu- is `fahrenhe`, but CLDR and everything else uses `fahrenheit` if (localeUnitCharString == "fahrenhe") {
localeUnitCharString = CharString("fahrenheit", status);
} // TODO: use the unit category as Java especially when all the categories are allowed.. if (localeUnitCharString == "celsius"
|| localeUnitCharString == "fahrenheit"
|| localeUnitCharString == "kelvin"
) {
UnitPreference unitPref;
unitPref.unit = localeUnitCharString.toStringPiece(); if (unitPref.unit.isEmpty() != localeUnitCharString.isEmpty()) {
status = U_MISSING_RESOURCE_ERROR; return result;
}
result.emplaceBackAndCheckErrorCode(status, unitPref); return result;
}
}
}
CharString region = ulocimp_getRegionForSupplementalData(locale.getName(), true, status);
U_ASSERT(idx >= 0); // Failures should have been taken care of by `status`. const UnitPreferenceMetadata *m = metadata_[idx];
if (isLocaleSystem) { // if the locale ID specifies a measurment system, check if ALL of the units we got back // are members of that system (or are "metric_adjacent", which we consider to match all // the systems) bool unitsMatchSystem = true;
ConversionRates rates(status); for (int32_t i = 0; unitsMatchSystem && i < m->prefsCount; i++) { const UnitPreference& unitPref = *(unitPrefs_[i + m->prefsOffset]);
MeasureUnitImpl measureUnit = MeasureUnitImpl::forIdentifier(unitPref.unit.data(), status); for (int32_t j = 0; unitsMatchSystem && j < measureUnit.singleUnits.length(); j++) { const SingleUnitImpl* singleUnit = measureUnit.singleUnits[j]; const ConversionRateInfo* rateInfo = rates.extractConversionInfo(singleUnit->getSimpleUnitID(), status); constchar* systems = rateInfo->systems.data(); // "metric-adjacent" is considered to match all the locale systems if (uprv_strstr(systems, "metric_adjacent") == nullptr) { if (uprv_strstr(systems, localeSystem.data()) == nullptr) {
unitsMatchSystem = false;
}
}
}
}
// if any of the units we got back above don't match the mearurement system the locale ID asked for, // throw out the region and just load the units for the base region for the requested measurement system if (!unitsMatchSystem) {
region.clear(); if (localeSystem == "ussystem") {
region.append("US", status);
} elseif (localeSystem == "uksystem") {
region.append("GB", status);
} else {
region.append("001", status);
}
idx = getPreferenceMetadataIndex(&metadata_, category, usage, region.toStringPiece(), status); if (U_FAILURE(status)) { return result;
}
m = metadata_[idx];
}
}
for (int32_t i = 0; i < m->prefsCount; i++) {
result.emplaceBackAndCheckErrorCode(status, *(unitPrefs_[i + m->prefsOffset]));
} return result;
}
} // namespace units
U_NAMESPACE_END
#endif/* #if !UCONFIG_NO_FORMATTING */
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-08-26)
¤
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.