From 38ab91d8751bec5d48acdcef81e406decd664f49 Mon Sep 17 00:00:00 2001
From: Hugo van der Merwe <17109322+hugovdm@users.noreply.github.com>
Date: Mon, 30 Mar 2020 20:47:40 +0200
Subject: [PATCH] Have getConversionRatesInfo accept a MaybeStackVector instead
 of only source and target.

---
 icu4c/source/i18n/unitsdata.cpp              | 19 ++++++++----------
 icu4c/source/i18n/unitsdata.h                | 12 +++++------
 icu4c/source/test/intltest/unitsdatatest.cpp | 21 ++++++++++++++------
 3 files changed, 28 insertions(+), 24 deletions(-)

diff --git a/icu4c/source/i18n/unitsdata.cpp b/icu4c/source/i18n/unitsdata.cpp
index aa527db337e..db9f6534147 100644
--- a/icu4c/source/i18n/unitsdata.cpp
+++ b/icu4c/source/i18n/unitsdata.cpp
@@ -282,26 +282,23 @@ void processSingleUnit(const MeasureUnit &unit, const UResourceBundle *convertUn
 
 } // namespace
 
-MaybeStackVector<ConversionRateInfo>
-getConversionRatesInfo(const MeasureUnit source, const MeasureUnit target, UErrorCode &status) {
+MaybeStackVector<ConversionRateInfo> U_I18N_API
+getConversionRatesInfo(const MaybeStackVector<MeasureUnit> &units, UErrorCode &status) {
     MaybeStackVector<ConversionRateInfo> result;
     if (U_FAILURE(status)) return result;
 
-    int32_t sourceUnitsLength, targetUnitsLength;
-    LocalArray<MeasureUnit> sourceUnits = source.splitToSingleUnits(sourceUnitsLength, status);
-    LocalArray<MeasureUnit> targetUnits = target.splitToSingleUnits(targetUnitsLength, status);
-
     LocalUResourceBundlePointer unitsBundle(ures_openDirect(NULL, "units", &status));
     StackUResourceBundle convertUnitsBundle;
     ures_getByKey(unitsBundle.getAlias(), "convertUnits", convertUnitsBundle.getAlias(), &status);
     ConversionRateDataSink convertSink(result);
 
-    for (int i = 0; i < sourceUnitsLength; i++) {
-        processSingleUnit(sourceUnits[i], convertUnitsBundle.getAlias(), convertSink, status);
-    }
+    for (int i = 0; i < units.length(); i++) {
+        int32_t numSingleUnits;
+        LocalArray<MeasureUnit> singleUnits = units[i]->splitToSingleUnits(numSingleUnits, status);
 
-    for (int i = 0; i < targetUnitsLength; i++) {
-        processSingleUnit(targetUnits[i], convertUnitsBundle.getAlias(), convertSink, status);
+        for (int i = 0; i < numSingleUnits; i++) {
+            processSingleUnit(singleUnits[i], convertUnitsBundle.getAlias(), convertSink, status);
+        }
     }
     return result;
 }
diff --git a/icu4c/source/i18n/unitsdata.h b/icu4c/source/i18n/unitsdata.h
index 6d6b737250c..c2dc0f1b7ca 100644
--- a/icu4c/source/i18n/unitsdata.h
+++ b/icu4c/source/i18n/unitsdata.h
@@ -48,16 +48,14 @@ struct U_I18N_API UnitPreference {
 };
 
 /**
- * Collects and returns ConversionRateInfo needed for conversions from source
- * and to target.
+ * Collects and returns ConversionRateInfo needed for conversions for a set of
+ * units.
  *
- * @param source The source unit (the unit type converted from).
- * @param target The target unit (the unit type converted to).
+ * @param units The units for which to load conversion data.
  * @param status Receives status.
  */
-MaybeStackVector<ConversionRateInfo> U_I18N_API getConversionRatesInfo(MeasureUnit source,
-                                                                       MeasureUnit target,
-                                                                       UErrorCode &status);
+MaybeStackVector<ConversionRateInfo>
+    U_I18N_API getConversionRatesInfo(const MaybeStackVector<MeasureUnit> &units, UErrorCode &status);
 
 /**
  * Collects the data needed for converting the inputUnit type to output units
diff --git a/icu4c/source/test/intltest/unitsdatatest.cpp b/icu4c/source/test/intltest/unitsdatatest.cpp
index f61f85fe822..bab60f87956 100644
--- a/icu4c/source/test/intltest/unitsdatatest.cpp
+++ b/icu4c/source/test/intltest/unitsdatatest.cpp
@@ -59,12 +59,21 @@ void UnitsDataTest::testGetConversionRateInfo() {
         logln("---testing: source=\"%s\", target=\"%s\"", t.sourceUnit, t.targetUnit);
         IcuTestErrorCode status(*this, "testGetConversionRateInfo");
 
-        MeasureUnit sourceUnit = MeasureUnit::forIdentifier(t.sourceUnit, status);
-        MeasureUnit targetUnit = MeasureUnit::forIdentifier(t.targetUnit, status);
-        MaybeStackVector<ConversionRateInfo> conversionInfo =
-            getConversionRatesInfo(sourceUnit, targetUnit, status);
-        if (status.errIfFailureAndReset("getConversionRatesInfo(<%s>, <%s>, ...)",
-                                        sourceUnit.getIdentifier(), targetUnit.getIdentifier())) {
+        MaybeStackVector<MeasureUnit> units;
+        MeasureUnit *item = units.emplaceBack(MeasureUnit::forIdentifier(t.sourceUnit, status));
+        if (!item) {
+            status.set(U_MEMORY_ALLOCATION_ERROR);
+            return;
+        }
+        item = units.emplaceBack(MeasureUnit::forIdentifier(t.targetUnit, status));
+        if (!item) {
+            status.set(U_MEMORY_ALLOCATION_ERROR);
+            return;
+        }
+
+        MaybeStackVector<ConversionRateInfo> conversionInfo = getConversionRatesInfo(units, status);
+        if (status.errIfFailureAndReset("getConversionRatesInfo({<%s>, <%s>}, ...)", t.sourceUnit,
+                                        t.targetUnit)) {
             continue;
         }
 
-- 
2.40.0