Merge pull request #43 from hugovdm/getUnitCategory

Add getUnitCategory()
This commit is contained in:
Hugo 2020-05-14 21:42:45 +02:00 committed by GitHub
commit d406b915c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 0 deletions

View file

@ -357,6 +357,29 @@ int32_t getPreferenceMetadataIndex(const MaybeStackVector<UnitPreferenceMetadata
} // namespace
CharString U_I18N_API getUnitCategory(const char *baseUnitIdentifier, UErrorCode &status) {
CharString result;
LocalUResourceBundlePointer unitsBundle(ures_openDirect(NULL, "units", &status));
LocalUResourceBundlePointer unitQuantities(
ures_getByKey(unitsBundle.getAlias(), "unitQuantities", NULL, &status));
int32_t categoryLength;
if (U_FAILURE(status)) { return result; }
const UChar *uCategory =
ures_getStringByKey(unitQuantities.getAlias(), baseUnitIdentifier, &categoryLength, &status);
if (U_FAILURE(status)) {
// TODO(CLDR-13787,hugovdm): special-casing the consumption-inverse
// case. Once CLDR-13787 is clarified, this should be generalised (or
// possibly removed):
if (uprv_strcmp(baseUnitIdentifier, "meter-per-cubic-meter") == 0) {
status = U_ZERO_ERROR;
result.append("consumption-inverse", status);
return result;
}
}
result.appendInvariantChars(uCategory, categoryLength, status);
return result;
}
// TODO: this may be unnecessary. Fold into ConversionRates class? Or move to anonymous namespace?
void U_I18N_API getAllConversionRates(MaybeStackVector<ConversionRateInfo> &result, UErrorCode &status) {
LocalUResourceBundlePointer unitsBundle(ures_openDirect(NULL, "units", &status));

View file

@ -14,6 +14,22 @@
U_NAMESPACE_BEGIN
/**
* Looks up the unit category of a base unit identifier.
*
* Only supports base units, other units must be resolved to base units before
* passing to this function.
*
* Categories are found in `unitQuantities` in the `units` resource (see
* `units.txt`).
*
* TODO(hugovdm): if we give unitsdata.cpp access to the functionality of
* `extractCompoundBaseUnit` which is currently in unitconverter.cpp, we could
* support all units for which there is a category. Does it make sense to move
* that function to unitsdata.cpp?
*/
CharString U_I18N_API getUnitCategory(const char *baseUnitIdentifier, UErrorCode &status);
/**
* Encapsulates "convertUnits" information from units resources, specifying how
* to convert from one unit to another.

View file

@ -12,6 +12,7 @@ class UnitsDataTest : public IntlTest {
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = NULL);
void testGetUnitCategory();
void testGetAllConversionRates();
void testGetPreferences();
};
@ -21,11 +22,34 @@ extern IntlTest *createUnitsDataTest() { return new UnitsDataTest(); }
void UnitsDataTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) {
if (exec) { logln("TestSuite UnitsDataTest: "); }
TESTCASE_AUTO_BEGIN;
TESTCASE_AUTO(testGetUnitCategory);
TESTCASE_AUTO(testGetAllConversionRates);
TESTCASE_AUTO(testGetPreferences);
TESTCASE_AUTO_END;
}
void UnitsDataTest::testGetUnitCategory() {
struct TestCase {
const char *unit;
const char *expectedCategory;
} testCases[]{
{"kilogram-per-cubic-meter", "mass-density"},
{"cubic-meter-per-meter", "consumption"},
// TODO(CLDR-13787,hugovdm): currently we're treating
// consumption-inverse as a separate category. Once consumption
// preference handling has been clarified by CLDR-13787, this function
// should be fixed.
{"meter-per-cubic-meter", "consumption-inverse"},
};
IcuTestErrorCode status(*this, "testGetUnitCategory");
for (const auto &t : testCases) {
CharString category = getUnitCategory(t.unit, status);
status.errIfFailureAndReset("getUnitCategory(%s)", t.unit);
assertEquals("category", t.expectedCategory, category.data());
}
}
void UnitsDataTest::testGetAllConversionRates() {
IcuTestErrorCode status(*this, "testGetAllConversionRates");
MaybeStackVector<ConversionRateInfo> conversionInfo;