--- /dev/null
+// © 2020 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+
+#include "cmemory.h"
+#include "complexunitsconverter.h"
+#include "uassert.h"
+#include "unicode/fmtable.h"
+#include "unitconverter.h"
+
+U_NAMESPACE_BEGIN
+
+ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnit inputUnit,
+ const MaybeStackVector<MeasureUnit> outputUnits,
+ UErrorCode &status) {
+ if (outputUnits.length() == 0) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
+
+ MaybeStackVector<UnitConverter> converters;
+ for (int i = 0, n = outputUnits.length(); i < n; i++) {
+ if (i == 0) { // first element
+ converters.emplaceBack(UnitConverter(inputUnit, *outputUnits[i], status));
+
+ } else {
+ converters.emplaceBack(UnitConverter(*outputUnits[i - 1], *outputUnits[i], status));
+ }
+
+ if (U_FAILURE(status)) break;
+ }
+
+ if (U_FAILURE(status)) return;
+
+ unitConverters_.appendAll(converters, status);
+ units_.appendAll(outputUnits, status);
+}
+
+UBool ComplexUnitsConverter::greaterThanOrEqual(double quantity, double limit) {
+ U_ASSERT(unitConverters_.length() ?> 0);
+
+ // first quantity is the biggest one.
+ double newQuantity = (*unitConverters_[0]).convert(quantity);
+
+ return newQuantity >= limit;
+}
+
+MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity, UErrorCode &status) {
+ MaybeStackVector<Measure> result;
+
+ for (int i = 0, n = unitConverters_.length(); i < n; ++i) {
+ quantity = (*unitConverters_[i]).convert(quantity);
+ if (i < n - 1) { // not last element
+ int64_t newQuantity = quantity;
+ Formattable formattableNewQuantity(newQuantity);
+ result.emplaceBack(Measure(formattableNewQuantity, units_[i], status));
+
+ quantity -= newQuantity;
+ } else { // Last element
+ Formattable formattableQuantity(quantity);
+ result.emplaceBack(Measure(formattableQuantity, units_[i], status));
+ }
+ }
+
+ return result;
+}
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
\ No newline at end of file
--- /dev/null
+// © 2020 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
+
+#include "unicode/utypes.h"
+
+#if !UCONFIG_NO_FORMATTING
+#ifndef __COMPLEXUNITSCONVERTER_H__
+#define __COMPLEXUNITSCONVERTER_H__
+
+#include "cmemory.h"
+#include "unitconverter.h"
+
+#include "unicode/errorcode.h"
+#include "unicode/measunit.h"
+#include "unicode/measure.h"
+
+U_NAMESPACE_BEGIN
+
+class U_I18N_API ComplexUnitsConverter {
+ public:
+ /**
+ * Constructor of `ComplexUnitsConverter`.
+ * NOTE:
+ * - inputUnit and outputUnits must be under the same category
+ * - e.g. meter to feet and inches --> all of them are length units.
+ * - outputUnits must be ordered in a descending order depending on their size.
+ * - e.g. mile, feet , inches.
+ * @param inputUnit represents the source unit.
+ * @param outputUnits a pointer to an array or the target units.
+ * @param lengthOfOutputUnits represents the length of the output units.
+ * @param status
+ */
+ ComplexUnitsConverter(const MeasureUnit inputUnit, const MaybeStackVector<MeasureUnit> outputUnits,
+ UErrorCode &status);
+
+ // Returns true if the `quantity` in the `inputUnit` is greater than or equal than the `limit` in the
+ // biggest `outputUnits`
+ UBool greaterThanOrEqual(double quantity, double limit);
+
+ // Returns outputMeasures which is an array with the correspinding values.
+ // - E.g. converting meters to feet and inches.
+ // 1 meter --> 3 feet, 3.3701 inches
+ // NOTE:
+ // the smallest element is the only element that could has fraction values.
+ MaybeStackVector<Measure> convert(double quantity, UErrorCode &status);
+
+ private:
+ MaybeStackVector<UnitConverter> unitConverters_;
+ MaybeStackVector<MeasureUnit> units_;
+};
+
+U_NAMESPACE_END
+
+#endif //__COMPLEXUNITSCONVERTER_H__
+
+#endif /* #if !UCONFIG_NO_FORMATTING */