Renaming and refactoring

This commit is contained in:
Shane F. Carr 2020-01-16 22:17:46 +01:00
parent 8fa2783695
commit 05ec2aea59
3 changed files with 186 additions and 146 deletions

View file

@ -87,7 +87,7 @@ const struct SIPrefixStrings {
{ "yocto", UMEASURE_SI_PREFIX_YOCTO },
};
// FIXME: Get this list from data
// TODO(ICU-20920): Get this list from data
const char16_t* const gSimpleUnits[] = {
u"one", // note: expected to be index 0
u"100kilometer",
@ -308,7 +308,7 @@ private:
int32_t fMatch;
};
struct PowerUnit {
struct SingleUnit {
int8_t power = 1;
UMeasureSIPrefix siPrefix = UMEASURE_SI_PREFIX_ONE;
int32_t simpleUnitIndex = 0;
@ -357,13 +357,13 @@ struct PowerUnit {
class CompoundUnit {
public:
typedef MaybeStackVector<PowerUnit, 3> PowerUnitList;
typedef MaybeStackVector<SingleUnit, 3> SingleUnitList;
void append(PowerUnit&& powerUnit, UErrorCode& status) {
if (powerUnit.power >= 0) {
appendImpl(numerator, std::move(powerUnit), status);
void append(SingleUnit&& singleUnit, UErrorCode& status) {
if (singleUnit.power >= 0) {
appendImpl(numerator, std::move(singleUnit), status);
} else {
appendImpl(denominator, std::move(powerUnit), status);
appendImpl(denominator, std::move(singleUnit), status);
}
}
@ -373,7 +373,7 @@ public:
denominator = std::move(temp);
}
void appendTo(CharString& builder, UErrorCode& status) {
void appendTo(CharString& builder, UErrorCode& status) const {
if (numerator.length() == 0) {
builder.append("one", status);
} else {
@ -385,19 +385,23 @@ public:
}
}
const PowerUnitList& getNumeratorUnits() {
const SingleUnitList& getNumeratorUnits() const {
return numerator;
}
const PowerUnitList& getDenominatorUnits() {
const SingleUnitList& getDenominatorUnits() const {
return denominator;
}
private:
PowerUnitList numerator;
PowerUnitList denominator;
bool isSingle() const {
return numerator.length() + denominator.length() == 1;
}
void appendToImpl(const PowerUnitList& unitList, int32_t len, CharString& builder, UErrorCode& status) {
private:
SingleUnitList numerator;
SingleUnitList denominator;
void appendToImpl(const SingleUnitList& unitList, int32_t len, CharString& builder, UErrorCode& status) const {
bool first = true;
for (int32_t i = 0; i < len; i++) {
if (first) {
@ -409,23 +413,23 @@ private:
}
}
void appendImpl(PowerUnitList& unitList, PowerUnit&& powerUnit, UErrorCode& status) {
void appendImpl(SingleUnitList& unitList, SingleUnit&& singleUnit, UErrorCode& status) {
// Check that the same simple unit doesn't already exist
for (int32_t i = 0; i < unitList.length(); i++) {
PowerUnit* candidate = unitList[i];
if (candidate->simpleUnitIndex == powerUnit.simpleUnitIndex
&& candidate->siPrefix == powerUnit.siPrefix) {
candidate->power += powerUnit.power;
SingleUnit* candidate = unitList[i];
if (candidate->simpleUnitIndex == singleUnit.simpleUnitIndex
&& candidate->siPrefix == singleUnit.siPrefix) {
candidate->power += singleUnit.power;
return;
}
}
// Add a new unit
PowerUnit* destination = unitList.emplaceBack();
SingleUnit* destination = unitList.emplaceBack();
if (!destination) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
*destination = std::move(powerUnit);
*destination = std::move(singleUnit);
}
};
@ -446,10 +450,10 @@ public:
return fIndex < fSource.length();
}
PowerUnit getOnlyPowerUnit(UErrorCode& status) {
SingleUnit getOnlySingleUnit(UErrorCode& status) {
bool sawPlus;
PowerUnit retval;
nextPowerUnit(retval, sawPlus, status);
SingleUnit retval;
nextSingleUnit(retval, sawPlus, status);
if (U_FAILURE(status)) {
return retval;
}
@ -468,13 +472,13 @@ public:
}
while (hasNext()) {
int32_t previ = fIndex;
PowerUnit powerUnit;
nextPowerUnit(powerUnit, sawPlus, status);
SingleUnit singleUnit;
nextSingleUnit(singleUnit, sawPlus, status);
if (sawPlus) {
fIndex = previ;
break;
}
result.append(std::move(powerUnit), status);
result.append(std::move(singleUnit), status);
}
return;
}
@ -537,7 +541,7 @@ private:
return Token(match);
}
void nextPowerUnit(PowerUnit& result, bool& sawPlus, UErrorCode& status) {
void nextSingleUnit(SingleUnit& result, bool& sawPlus, UErrorCode& status) {
sawPlus = false;
if (U_FAILURE(status)) {
return;
@ -607,7 +611,7 @@ private:
case Token::TYPE_ONE:
// Skip "one" and go to the next unit
return nextPowerUnit(result, sawPlus, status);
return nextSingleUnit(result, sawPlus, status);
case Token::TYPE_SIMPLE_UNIT:
result.simpleUnitIndex = token.getSimpleUnitIndex();
@ -654,42 +658,61 @@ MeasureUnit MeasureUnit::forIdentifier(const char* identifier, UErrorCode& statu
return MeasureUnit(builder.cloneData(status));
}
UMeasureUnitComplexity MeasureUnit::getComplexity(UErrorCode& status) const {
const char* id = getIdentifier();
UnitIdentifierParser parser = UnitIdentifierParser::from(id, status);
if (U_FAILURE(status)) {
// Unrecoverable error
return UMEASURE_UNIT_SINGLE;
}
CompoundUnit compoundUnit;
parser.nextCompoundUnit(compoundUnit, status);
if (compoundUnit.isSingle()) {
return UMEASURE_UNIT_SINGLE;
} else if (parser.hasNext()) {
return UMEASURE_UNIT_SEQUENCE;
} else {
return UMEASURE_UNIT_COMPOUND;
}
}
UMeasureSIPrefix MeasureUnit::getSIPrefix(UErrorCode& status) const {
const char* id = getIdentifier();
return UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status).siPrefix;
return UnitIdentifierParser::from(id, status).getOnlySingleUnit(status).siPrefix;
}
MeasureUnit MeasureUnit::withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const {
const char* id = getIdentifier();
PowerUnit powerUnit = UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status);
SingleUnit singleUnit = UnitIdentifierParser::from(id, status).getOnlySingleUnit(status);
if (U_FAILURE(status)) {
return *this;
}
powerUnit.siPrefix = prefix;
singleUnit.siPrefix = prefix;
CharString builder;
powerUnit.appendTo(builder, status);
singleUnit.appendTo(builder, status);
return MeasureUnit(builder.cloneData(status));
}
int8_t MeasureUnit::getPower(UErrorCode& status) const {
const char* id = getIdentifier();
return UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status).power;
return UnitIdentifierParser::from(id, status).getOnlySingleUnit(status).power;
}
MeasureUnit MeasureUnit::withPower(int8_t power, UErrorCode& status) const {
const char* id = getIdentifier();
PowerUnit powerUnit = UnitIdentifierParser::from(id, status).getOnlyPowerUnit(status);
SingleUnit singleUnit = UnitIdentifierParser::from(id, status).getOnlySingleUnit(status);
if (U_FAILURE(status)) {
return *this;
}
CharString builder;
powerUnit.power = power;
singleUnit.power = power;
if (power < 0) {
builder.append("one-per-", status);
}
powerUnit.appendTo(builder, status);
singleUnit.appendTo(builder, status);
return MeasureUnit(builder.cloneData(status));
}
@ -729,15 +752,15 @@ MeasureUnit MeasureUnit::product(const MeasureUnit& other, UErrorCode& status) c
return MeasureUnit(builder.cloneData(status));
}
LocalArray<MeasureUnit> MeasureUnit::getSimpleUnits(UErrorCode& status) const {
LocalArray<MeasureUnit> MeasureUnit::getSingleUnits(UErrorCode& status) const {
const char* id = getIdentifier();
CompoundUnit compoundUnit = UnitIdentifierParser::from(id, status).getOnlyCompoundUnit(status);
if (U_FAILURE(status)) {
return LocalArray<MeasureUnit>::withLength(nullptr, 0);
}
const CompoundUnit::PowerUnitList& numerator = compoundUnit.getNumeratorUnits();
const CompoundUnit::PowerUnitList& denominator = compoundUnit.getDenominatorUnits();
const CompoundUnit::SingleUnitList& numerator = compoundUnit.getNumeratorUnits();
const CompoundUnit::SingleUnitList& denominator = compoundUnit.getDenominatorUnits();
int32_t count = numerator.length() + denominator.length();
MeasureUnit* arr = new MeasureUnit[count];

View file

@ -31,6 +31,44 @@ U_NAMESPACE_BEGIN
class StringEnumeration;
/**
* Enumeration for unit complexity. There are three levels:
*
* - SINGLE: A single unit, optionally with a power and/or SI prefix. Examples: hectare,
* square-kilometer, kilojoule, one-per-second.
* - COMPOUND: A unit composed of the product of multiple single units. Examples:
* meter-per-second, kilowatt-hour, kilogram-meter-per-square-second.
* - SEQUENCE: A unit composed of the sum of multiple compound units. Examples: foot+inch,
* hour+minute+second, hectare+square-meter.
*
* The complexity determines which operations are available. For example, you cannot set the power
* or SI prefix of a compound unit.
*
* @draft ICU 67
*/
enum UMeasureUnitComplexity {
/**
* A single unit, like kilojoule.
*
* @draft ICU 67
*/
UMEASURE_UNIT_SINGLE,
/**
* A compound unit, like meter-per-second.
*
* @draft ICU 67
*/
UMEASURE_UNIT_COMPOUND,
/**
* A sequence unit, like hour+minute.
*
* @draft ICU 67
*/
UMEASURE_UNIT_SEQUENCE
};
/**
* Enumeration for SI prefixes, such as "kilo".
*
@ -297,60 +335,74 @@ class U_I18N_API MeasureUnit: public UObject {
const char* getIdentifier() const;
/**
* Creates a MeasureUnit which is this MeasureUnit augmented with the specified SI prefix.
* Compute the complexity of the unit. See UMeasureUnitComplexity for more information.
*
* @param status Set if an error occurs.
* @return The unit complexity.
* @draft ICU 67
*/
UMeasureUnitComplexity getComplexity(UErrorCode& status) const;
/**
* Creates a MeasureUnit which is this SINGLE unit augmented with the specified SI prefix.
* For example, UMEASURE_SI_PREFIX_KILO for "kilo".
*
* There is sufficient locale data to format all standard SI prefixes.
*
* This method only works if the MeasureUnit is composed of only one simple unit. An error
* will be set if called on a MeasureUnit containing multiple units.
* NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will
* occur. For more information, see UMeasureUnitComplexity.
*
* @param prefix The SI prefix, from UMeasureSIPrefix.
* @param status ICU error code
* @return A new MeasureUnit.
* @param status Set if this is not a SINGLE unit or if another error occurs.
* @return A new SINGLE unit.
*/
MeasureUnit withSIPrefix(UMeasureSIPrefix prefix, UErrorCode& status) const;
/**
* Gets the current SI prefix of this MeasureUnit. For example, if the unit has the SI prefix
* Gets the current SI prefix of this SINGLE unit. For example, if the unit has the SI prefix
* "kilo", then UMEASURE_SI_PREFIX_KILO is returned.
*
* If the MeasureUnit is composed of multiple simple units, the SI prefix of the first simple
* unit is returned. For example, from "centimeter-kilogram-per-second", the SI prefix
* UMEASURE_SI_PREFIX_CENTI will be returned.
* NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will
* occur. For more information, see UMeasureUnitComplexity.
*
* @return The SI prefix of the first simple unit, from UMeasureSIPrefix.
* @param status Set if this is not a SINGLE unit or if another error occurs.
* @return The SI prefix of this SINGLE unit, from UMeasureSIPrefix.
*/
UMeasureSIPrefix getSIPrefix(UErrorCode& status) const;
/**
* Creates a MeasureUnit which is this MeasureUnit augmented with the specified power. For
* Creates a MeasureUnit which is this SINGLE unit augmented with the specified power. For
* example, if power is 2, the unit will be squared.
*
* This method only works if the MeasureUnit is composed of only one simple unit. An error
* will be set if called on a MeasureUnit containing multiple units.
* NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will
* occur. For more information, see UMeasureUnitComplexity.
*
* @param power The power.
* @param status ICU error code
* @return A new MeasureUnit.
* @param status Set if this is not a SINGLE unit or if another error occurs.
* @return A new SINGLE unit.
*/
MeasureUnit withPower(int8_t power, UErrorCode& status) const;
/**
* Gets the power of this MeasureUnit. For example, if the unit is square, then 2 is returned.
*
* If the MeasureUnit is composed of multiple simple units, the power of the first simple unit
* is returned. For example, from "cubic-meter-per-square-second", 3 is returned.
* NOTE: Only works on SINGLE units. If this is a COMPOUND or SEQUENCE unit, an error will
* occur. For more information, see UMeasureUnitComplexity.
*
* @return The power of the first simple unit.
* @param status Set if this is not a SINGLE unit or if another error occurs.
* @return The power of this simple unit.
*/
int8_t getPower(UErrorCode& status) const;
/**
* Gets the reciprocal of the unit, with the numerator and denominator flipped.
* Gets the reciprocal of this MeasureUnit, with the numerator and denominator flipped.
*
* For example, if the receiver is "meter-per-second", the unit "second-per-meter" is returned.
*
* NOTE: Only works on SINGLE and COMPOUND units. If this is a SEQUENCE unit, an error will
* occur. For more information, see UMeasureUnitComplexity.
*
* @param status Set if this is a SEQUENCE unit or if another error occurs.
* @return The reciprocal of the target unit.
*/
MeasureUnit reciprocal(UErrorCode& status) const;
@ -364,88 +416,42 @@ class U_I18N_API MeasureUnit: public UObject {
* For example, if the receiver is "kilowatt" and the argument is "hour-per-day", then the
* unit "kilowatt-hour-per-day" is returned.
*
* NOTE: Only works on SINGLE and COMPOUND units. If either unit (receivee and argument) is a
* SEQUENCE unit, an error will occur. For more information, see UMeasureUnitComplexity.
*
* @param status Set if this or other is a SEQUENCE unit or if another error occurs.
* @return The product of the target unit with the provided unit.
*/
MeasureUnit product(const MeasureUnit& other, UErrorCode& status) const;
/**
* Gets the number of constituent simple units.
* Gets the list of single units contained within a compound unit.
*
* For example, if the receiver is "meter-per-square-second", then 2 is returned, since there
* are two simple units: "meter" and "second".
* For example, given "meter-kilogram-per-second", three units will be returned: "meter",
* "kilogram", and "one-per-second".
*
* @return The number of constituent units.
* If this is a SINGLE unit, an array of length 1 will be returned.
*
* NOTE: Only works on SINGLE and COMPOUND units. If this is a SEQUENCE unit, an error will
* occur. For more information, see UMeasureUnitComplexity.
*
* @param status Set if this is a SEQUENCE unit or if another error occurs.
* @return An array of single units, owned by the caller.
*/
size_t getSimpleUnitCount(UErrorCode& status) const;
LocalArray<MeasureUnit> getSimpleUnits(UErrorCode& status) const;
LocalArray<MeasureUnit> getSequenceUnits(UErrorCode& status) const;
LocalArray<MeasureUnit> getSingleUnits(UErrorCode& status) const;
/**
* Gets the constituent unit at the given index.
*
* For example, to loop over all simple units:
*
* <pre>
* MeasureUnit unit(u"meter-per-square-second");
* for (size_t i = 0; i < unit.getSimpleUnitCount(); i++) {
* std::cout << unit.simpleUnitAt(i).toString() << std::endl;
* }
* </pre>
*
* Expected output: meter, one-per-square-second
*
* @param index Zero-based index. If out of range, the dimensionless unit is returned.
* @return The constituent simple unit at the specified position.
* Gets the list of compound units contained within a sequence unit.
*
* For example, given "hour+minute+second", three units will be returned: "hour", "minute",
* and "second".
*
* If this is a SINGLE or COMPOUND unit, an array of length 1 will be returned.
*
* @param status Set of an error occurs.
* @return An array of compound units, owned by the caller.
*/
MeasureUnit simpleUnitAt(size_t index, UErrorCode& status) const;
/**
* Composes this unit with a super unit.
*
* A super unit, used for formatting only, should be a larger unit sharing the same dimension.
* For example, if the current unit is "inch", a super unit could be "foot", in order to
* render 71 inches as "5 feet, 11 inches". If the super unit is invalid, an error will occur
* during formatting.
*
* A unit can have multiple super units; for example, "second" could have both "minute" and
* "hour" as super units.
*
* Super units are ignored and left untouched in most other methods, such as withSIPrefix,
* withPower, and reciprocal.
*
* @param other The super unit to compose with the target unit.
* @return The composition of the given super unit with this unit.
*/
MeasureUnit withSuperUnit(const MeasureUnit& other, UErrorCode& status) const;
/**
* Gets the number of super units in the receiver.
*
* For example, "foot+inch" has one super unit.
*
* @return The number of super units.
*/
size_t getSuperUnitCount(UErrorCode& status) const;
/**
* Gets the super unit at the given index.
*
* For example, to loop over all super units:
*
* <pre>
* MeasureUnit unit(u"hour+minute+second");
* for (size_t i = 0; i < unit.getSuperUnitCount(); i++) {
* std::cout << unit.superUnitAt(i).toCoreUnitIdentifier() << std::endl;
* }
* </pre>
*
* Expected output: hour, minute
*
* @return The super unit at the specified position.
*/
MeasureUnit superUnitAt(size_t index, UErrorCode& status) const;
LocalArray<MeasureUnit> getCompoundUnits(UErrorCode& status) const;
/**
* getAvailable gets all of the available units.

View file

@ -139,7 +139,7 @@ private:
NumberFormat::EAlignmentFields field,
int32_t start,
int32_t end);
void verifyPowerUnit(
void verifySingleUnit(
const MeasureUnit& unit,
UMeasureSIPrefix siPrefix,
int8_t power,
@ -3239,11 +3239,11 @@ void MeasureFormatTest::TestCompoundUnitOperations() {
MeasureUnit centimeter2 = meter.withSIPrefix(UMEASURE_SI_PREFIX_CENTI, status);
MeasureUnit cubicDecimeter = cubicMeter.withSIPrefix(UMEASURE_SI_PREFIX_DECI, status);
verifyPowerUnit(kilometer, UMEASURE_SI_PREFIX_KILO, 1, "kilometer");
verifyPowerUnit(meter, UMEASURE_SI_PREFIX_ONE, 1, "meter");
verifyPowerUnit(centimeter1, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter");
verifyPowerUnit(centimeter2, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter");
verifyPowerUnit(cubicDecimeter, UMEASURE_SI_PREFIX_DECI, 3, "cubic-decimeter");
verifySingleUnit(kilometer, UMEASURE_SI_PREFIX_KILO, 1, "kilometer");
verifySingleUnit(meter, UMEASURE_SI_PREFIX_ONE, 1, "meter");
verifySingleUnit(centimeter1, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter");
verifySingleUnit(centimeter2, UMEASURE_SI_PREFIX_CENTI, 1, "centimeter");
verifySingleUnit(cubicDecimeter, UMEASURE_SI_PREFIX_DECI, 3, "cubic-decimeter");
assertTrue("centimeter equality", centimeter1 == centimeter2);
assertTrue("kilometer inequality", centimeter1 != kilometer);
@ -3253,10 +3253,10 @@ void MeasureFormatTest::TestCompoundUnitOperations() {
MeasureUnit quarticKilometer = kilometer.withPower(4, status);
MeasureUnit overQuarticKilometer1 = kilometer.withPower(-4, status);
verifyPowerUnit(squareMeter, UMEASURE_SI_PREFIX_ONE, 2, "square-meter");
verifyPowerUnit(overCubicCentimeter, UMEASURE_SI_PREFIX_CENTI, -3, "one-per-cubic-centimeter");
verifyPowerUnit(quarticKilometer, UMEASURE_SI_PREFIX_KILO, 4, "p4-kilometer");
verifyPowerUnit(overQuarticKilometer1, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer");
verifySingleUnit(squareMeter, UMEASURE_SI_PREFIX_ONE, 2, "square-meter");
verifySingleUnit(overCubicCentimeter, UMEASURE_SI_PREFIX_CENTI, -3, "one-per-cubic-centimeter");
verifySingleUnit(quarticKilometer, UMEASURE_SI_PREFIX_KILO, 4, "p4-kilometer");
verifySingleUnit(overQuarticKilometer1, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer");
assertTrue("power inequality", quarticKilometer != overQuarticKilometer1);
@ -3266,8 +3266,8 @@ void MeasureFormatTest::TestCompoundUnitOperations() {
.product(kilometer, status)
.reciprocal(status);
verifyPowerUnit(overQuarticKilometer2, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer");
verifyPowerUnit(overQuarticKilometer3, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer");
verifySingleUnit(overQuarticKilometer2, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer");
verifySingleUnit(overQuarticKilometer3, UMEASURE_SI_PREFIX_KILO, -4, "one-per-p4-kilometer");
assertTrue("reciprocal equality", overQuarticKilometer1 == overQuarticKilometer2);
assertTrue("reciprocal equality", overQuarticKilometer1 == overQuarticKilometer3);
@ -3281,7 +3281,7 @@ void MeasureFormatTest::TestCompoundUnitOperations() {
MeasureUnit secondCentimeter = kiloSquareSecond.product(meter.withSIPrefix(UMEASURE_SI_PREFIX_CENTI, status), status);
MeasureUnit secondCentimeterPerKilometer = secondCentimeter.product(kilometer.reciprocal(status), status);
verifyPowerUnit(kiloSquareSecond, UMEASURE_SI_PREFIX_KILO, 2, "square-kilosecond");
verifySingleUnit(kiloSquareSecond, UMEASURE_SI_PREFIX_KILO, 2, "square-kilosecond");
const char* meterSecondSub[] = {"meter", "square-kilosecond"};
verifyCompoundUnit(meterSecond, "meter-square-kilosecond",
meterSecondSub, UPRV_LENGTHOF(meterSecondSub));
@ -3387,12 +3387,12 @@ void MeasureFormatTest::verifyFormat(
}
}
void MeasureFormatTest::verifyPowerUnit(
void MeasureFormatTest::verifySingleUnit(
const MeasureUnit& unit,
UMeasureSIPrefix siPrefix,
int8_t power,
const char* identifier) {
IcuTestErrorCode status(*this, "verifyPowerUnit");
IcuTestErrorCode status(*this, "verifySingleUnit");
UnicodeString uid(identifier, -1, US_INV);
assertEquals(uid + ": SI prefix",
siPrefix,
@ -3409,6 +3409,10 @@ void MeasureFormatTest::verifyPowerUnit(
assertTrue(uid + ": Constructor",
unit == MeasureUnit::forIdentifier(identifier, status));
status.errIfFailureAndReset("%s: Constructor", identifier);
assertEquals(uid + ": Complexity",
UMEASURE_UNIT_SINGLE,
unit.getComplexity(status));
status.errIfFailureAndReset("%s: Complexity", identifier);
}
void MeasureFormatTest::verifyCompoundUnit(
@ -3425,14 +3429,21 @@ void MeasureFormatTest::verifyCompoundUnit(
assertTrue(uid + ": Constructor",
unit == MeasureUnit::forIdentifier(identifier, status));
status.errIfFailureAndReset("%s: Constructor", identifier);
assertEquals(uid + ": Complexity",
UMEASURE_UNIT_COMPOUND,
unit.getComplexity(status));
status.errIfFailureAndReset("%s: Complexity", identifier);
LocalArray<MeasureUnit> subUnits = unit.getSimpleUnits(status);
LocalArray<MeasureUnit> subUnits = unit.getSingleUnits(status);
assertEquals(uid + ": Length", subIdentifierCount, subUnits.length());
for (int32_t i = 0;; i++) {
if (i >= subIdentifierCount || i >= subUnits.length()) break;
assertEquals(uid + ": Sub-unit #" + Int64ToUnicodeString(i),
subIdentifiers[i],
subUnits[i].getIdentifier());
assertEquals(uid + ": Sub-unit Complexity",
UMEASURE_UNIT_SINGLE,
subUnits[i].getComplexity(status));
}
}