]> granicus.if.org Git - icu/commitdiff
hook up the data to units router
authorYounies Mahmoud <younies.mahmoud@gmail.com>
Tue, 24 Mar 2020 13:05:01 +0000 (14:05 +0100)
committerYounies Mahmoud <younies.mahmoud@gmail.com>
Tue, 24 Mar 2020 13:05:01 +0000 (14:05 +0100)
icu4c/source/i18n/complexunitsconverter.cpp
icu4c/source/i18n/complexunitsconverter.h
icu4c/source/i18n/getunitsdata.h
icu4c/source/i18n/unitconverter.cpp
icu4c/source/i18n/unitconverter.h
icu4c/source/i18n/unitsrouter.cpp
icu4c/source/i18n/unitsrouter.h

index 6470eb9bd06cf1b7fb4a8b1d335e84ff07fd8a78..5a0a0879e7438e6878aa300f3869874fa343897c 100644 (file)
 #include "uassert.h"
 #include "unicode/fmtable.h"
 #include "unitconverter.h"
+#include "getunitsdata.h"
 
 U_NAMESPACE_BEGIN
 
 ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnit inputUnit, const MeasureUnit outputUnits,
+                                             const MaybeStackVector<ConversionRateInfo> &ratesInfo,
                                              UErrorCode &status) {
     auto singleUnits = outputUnits.splitToSingleUnits(status);
     MaybeStackVector<MeasureUnit> singleUnitsInOrder;
@@ -23,11 +25,12 @@ ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnit inputUnit, const
         singleUnitsInOrder.emplaceBack(singleUnits[i]);
     }
 
-    ComplexUnitsConverter(inputUnit, std::move(singleUnitsInOrder), status);
+    ComplexUnitsConverter(inputUnit, std::move(singleUnitsInOrder), ratesInfo, status);
 }
 
 ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnit inputUnit,
                                              const MaybeStackVector<MeasureUnit> outputUnits,
+                                             const MaybeStackVector<ConversionRateInfo> &ratesInfo,
                                              UErrorCode &status) {
     if (outputUnits.length() == 0) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -37,10 +40,10 @@ ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnit inputUnit,
     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));
+            converters.emplaceBack(inputUnit, *outputUnits[i], ratesInfo, status);
 
         } else {
-            converters.emplaceBack(UnitConverter(*outputUnits[i - 1], *outputUnits[i], status));
+            converters.emplaceBack(*outputUnits[i - 1], *outputUnits[i], ratesInfo, status);
         }
 
         if (U_FAILURE(status)) break;
index bd9e0e6f7ca3fe71dac7b09654aca519dd5f46ee..e0bd44765044ce153fc08992e5c83ce62a0add71 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "cmemory.h"
 #include "unitconverter.h"
-
+#include "getunitsdata.h"
 #include "unicode/errorcode.h"
 #include "unicode/measunit.h"
 #include "unicode/measure.h"
@@ -31,10 +31,10 @@ class U_I18N_API ComplexUnitsConverter {
      * @param status
      */
     ComplexUnitsConverter(const MeasureUnit inputUnit, const MaybeStackVector<MeasureUnit> outputUnits,
-                          UErrorCode &status);
+                          const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status);
 
     ComplexUnitsConverter(const MeasureUnit inputUnit, const MeasureUnit outputUnits,
-                          UErrorCode &status);
+                          const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status);
 
     // Returns true if the `quantity` in the `inputUnit` is greater than or equal than the `limit` in the
     // biggest `outputUnits`
index da7ab68051aa5cfd4cb36078b1a8bb5746b83c27..cdfb77a25d1d9799c958efd486ed32825029d8db 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "charstr.h" // CharString
 #include "cmemory.h"
-#include "complexunitsconverter.h"
 #include "unicode/errorcode.h"
 #include "unicode/measunit.h"
 #include "unicode/measure.h"
 
 U_NAMESPACE_BEGIN
 
-struct ConversionRateInfo {
+struct U_I18N_API ConversionRateInfo {
     CharString source;
     CharString target;
     CharString factor;
     CharString offset;
+    bool reciprocal = false;
 };
 
-struct UnitPreference {
+struct U_I18N_API UnitPreference {
     UnitPreference() : geq(1) {}
     CharString unit;
     double geq;
@@ -37,6 +37,10 @@ void U_I18N_API getUnitsData(const char *outputRegion, const char *usage, const
                              MaybeStackVector<ConversionRateInfo> &conversionInfo,
                              MaybeStackVector<UnitPreference> &unitPreferences, UErrorCode &status);
 
+// TODO(hugo): Implement
+MaybeStackVector<ConversionRateInfo>
+    U_I18N_API getConversionRatesInfo(MeasureUnit source, MeasureUnit target, UErrorCode &status);
+
 U_NAMESPACE_END
 
 #endif //__GETUNITSDATA_H__
index 65412848ebecbaad9cfa1d98045b7da07c4edc7b..32761f4af35644f571bfe5c80632b3fb1e02cd23 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "charstr.h"
 #include "double-conversion.h"
+#include "getunitsdata.h"
 #include "measunit_impl.h"
 #include "resource.h"
 #include "uassert.h"
@@ -185,14 +186,15 @@ class UnitConversionRatesSink : public ResourceSink {
     Factor *conversionFactor;
 };
 
-ConvertUnit extractConvertUnit(StringPiece source, const MaybeStackVector<ConvertUnit> &convertUnits,
-                               UErrorCode &status) {
-    for (int i = 0, n = convertUnits.length(); i < n; ++i) {
-        if (convertUnits[i]->source == source) return *convertUnits[i];
+const ConversionRateInfo& extractConversionRateInfo(StringPiece source,
+                                             const MaybeStackVector<ConversionRateInfo> &ratesInfo,
+                                             UErrorCode &status) {
+    for (int i = 0, n = ratesInfo.length(); i < n; ++i) {
+        if (ratesInfo[i]->source == source) return *ratesInfo[i];
     }
 
     status = U_INTERNAL_PROGRAM_ERROR;
-    return ConvertUnit();
+    return ConversionRateInfo();
 }
 
 /*/
@@ -292,24 +294,24 @@ void extractFactor(Factor &factor, StringPiece stringFactor, UErrorCode &status)
 
 // Load factor for a single source
 void loadSingleFactor(Factor &factor, StringPiece source,
-                      const MaybeStackVector<ConvertUnit> &convertUnits, UErrorCode &status) {
-    auto conversionUnit = extractConvertUnit(source, convertUnits, status);
+                      const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status) {
+    const auto& conversionUnit = extractConversionRateInfo(source, ratesInfo, status);
     if (U_FAILURE(status)) return;
 
-    extractFactor(factor, conversionUnit.factor, status);
-    factor.offset = strHasDivideSignToDouble(conversionUnit.offset);
+    extractFactor(factor, conversionUnit.factor.toStringPiece(), status);
+    factor.offset = strHasDivideSignToDouble(conversionUnit.offset.toStringPiece());
     factor.reciprocal = factor.reciprocal;
 }
 
 // Load Factor for compound source
 void loadCompoundFactor(Factor &factor, StringPiece source,
-                        const MaybeStackVector<ConvertUnit> &convertUnits, UErrorCode &status) {
+                        const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status) {
     auto compoundSourceUnit = MeasureUnitImpl::forIdentifier(source, status);
     for (int32_t i = 0, n = compoundSourceUnit.units.length(); i < n; i++) {
         auto singleUnit = *compoundSourceUnit.units[i]; // a TempSingleUnit
 
         Factor singleFactor;
-        loadSingleFactor(singleFactor, singleUnit.identifier, convertUnits, status);
+        loadSingleFactor(singleFactor, singleUnit.identifier, ratesInfo, status);
 
         // You must apply SiPrefix before the power, because the power may be will flip the factor.
         singleFactor.applySiPrefix(singleUnit.siPrefix);
@@ -370,7 +372,7 @@ UBool checkSimpleUnit(StringPiece unitIdentifier, UErrorCode &status) {
  *  Extract conversion rate from `source` to `target`
  */
 void loadConversionRate(ConversionRate &conversionRate, StringPiece source, StringPiece target,
-                        UnitsCase unitsCase, const MaybeStackVector<ConvertUnit> &convertUnits,
+                        UnitsCase unitsCase, const MaybeStackVector<ConversionRateInfo> &ratesInfo,
                         UErrorCode &status) {
     // Represents the conversion factor from the source to the target.
     Factor finalFactor;
@@ -383,8 +385,8 @@ void loadConversionRate(ConversionRate &conversionRate, StringPiece source, Stri
     /* Load needed factors. */
     // Load the conversion factor from the source to the target in the  which is considered as the Root
     // between
-    loadCompoundFactor(SourceToRoot, source, convertUnits, status);
-    loadCompoundFactor(TargetToRoot, target, convertUnits, status);
+    loadCompoundFactor(SourceToRoot, source, ratesInfo, status);
+    loadCompoundFactor(TargetToRoot, target, ratesInfo, status);
 
     // Merger Factors
     finalFactor.multiplyBy(SourceToRoot);
@@ -413,23 +415,23 @@ void loadConversionRate(ConversionRate &conversionRate, StringPiece source, Stri
     conversionRate.reciprocal = unitsCase == UnitsCase::RECIPROCAL;
 }
 
-StringPiece getTarget(StringPiece source, const MaybeStackVector<ConvertUnit> &convertUnits,
+StringPiece getTarget(StringPiece source, const MaybeStackVector<ConversionRateInfo> &ratesInfo,
                       UErrorCode &status) {
-    auto convertUnit = extractConvertUnit(source, convertUnits, status);
+    const auto& convertUnit = extractConversionRateInfo(source, ratesInfo, status);
     if (U_FAILURE(status)) return StringPiece("");
-    return convertUnit.target;
+    return convertUnit.target.toStringPiece();
 }
 
 // TODO(ICU-20568): Add more test coverage for this function.
 // Returns the target of a source unit.
-MeasureUnit extractTarget(MeasureUnit source, const MaybeStackVector<ConvertUnit> &convertUnits,
+MeasureUnit extractTarget(MeasureUnit source, const MaybeStackVector<ConversionRateInfo> &ratesInfo,
                           UErrorCode &status) {
     MeasureUnit result; // Empty unit.
     auto singleUnits = source.splitToSingleUnits(status);
 
     for (int i = 0; i < singleUnits.length(); i++) {
         const auto &singleUnit = singleUnits[i];
-        StringPiece target = getTarget(singleUnit.getIdentifier(), convertUnits, status);
+        StringPiece target = getTarget(singleUnit.getIdentifier(), ratesInfo, status);
 
         if (U_FAILURE(status)) return result;
 
@@ -458,9 +460,9 @@ MeasureUnit extractTarget(MeasureUnit source, const MaybeStackVector<ConvertUnit
 // UnitsCase::RECIPROCAL is returned, it means one's base unit is the inverse of
 // the other's.
 UnitsCase checkUnitsCase(const MeasureUnit &source, const MeasureUnit &target,
-                         const MaybeStackVector<ConvertUnit> &convertUnits, UErrorCode &status) {
-    MeasureUnit sourceTargetUnit = extractTarget(source, convertUnits, status);
-    MeasureUnit targetTargetUnit = extractTarget(target, convertUnits, status);
+                         const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status) {
+    MeasureUnit sourceTargetUnit = extractTarget(source, ratesInfo, status);
+    MeasureUnit targetTargetUnit = extractTarget(target, ratesInfo, status);
 
     if (sourceTargetUnit == targetTargetUnit) return UnitsCase::CONVERTIBLE;
     if (sourceTargetUnit == targetTargetUnit.reciprocal(status)) return UnitsCase::RECIPROCAL;
@@ -471,15 +473,15 @@ UnitsCase checkUnitsCase(const MeasureUnit &source, const MeasureUnit &target,
 } // namespace
 
 UnitConverter::UnitConverter(MeasureUnit source, MeasureUnit target,
-                             const MaybeStackVector<ConvertUnit> &convertUnits, UErrorCode &status) {
-    UnitsCase unitsCase = checkUnitsCase(source, target, convertUnits, status);
+                             const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status) {
+    UnitsCase unitsCase = checkUnitsCase(source, target, ratesInfo, status);
     if (U_FAILURE(status)) return;
 
     conversionRate_.source = source;
     conversionRate_.target = target;
 
     loadConversionRate(conversionRate_, source.getIdentifier(), target.getIdentifier(), unitsCase,
-                       convertUnits, status);
+                       ratesInfo, status);
 }
 
 double UnitConverter::convert(double inputValue) {
index 5bd164440e7b1c3af36a7c236eabb765e8a9530b..9549f5ee383af14fbea6343172706e5d4383be54 100644 (file)
@@ -8,6 +8,7 @@
 #define __UNITCONVERTER_H__
 
 #include "cmemory.h"
+#include "getunitsdata.h"
 #include "unicode/errorcode.h"
 #include "unicode/measunit.h"
 #include "unicode/measure.h"
 U_NAMESPACE_BEGIN
 // Data Skeleton.
 
-// Represents a raw convert unit.
-struct ConvertUnit {
-    StringPiece source;
-    StringPiece target;
-
-    // NOTE
-    //  If the source and target are equal, the factor will be "1"
-    StringPiece factor = "1";
-
-    // NOTE
-    //  If the offset is not exist, its value will be "0"
-    StringPiece offset = "0";
-
-    // NOTE
-    //  If reciprocal is not exits, its value will be `false`
-    bool reciprocal = false;
-};
-
 /**
  * Represents the conversion rate between `source` and `target`.
  */
@@ -62,8 +45,8 @@ class U_I18N_API UnitConverter {
      * @param target represents the target unit.
      * @param status
      */
-    UnitConverter(MeasureUnit source, MeasureUnit target, const MaybeStackVector<ConvertUnit>& convertUnits,
-                  UErrorCode &status);
+    UnitConverter(MeasureUnit source, MeasureUnit target,
+                  const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status);
 
     /**
      * Convert a value in the source unit to another value in the target unit.
index f727cfa1522381e26f6bae32406062c7874ff3b7..db6018c9f47d4cdb563cff78727c419ebcff50aa 100644 (file)
@@ -33,9 +33,9 @@ UnitsRouter::UnitsRouter(MeasureUnit inputUnit, StringPiece locale, StringPiece
     for (int i = 0, n = unitPreferences.length(); i < n; ++i) {
         const auto &preference = *unitPreferences[i];
         MeasureUnit complexTargetUnit = MeasureUnit::forIdentifier(preference.unit.data(), status);
-        // TODO(younies): Find a way to emplaceBack `ConverterPreference`
-        // converterPreferences_.emplaceBack(
-        //     std::move(ConverterPreference(inputUnit, complexTargetUnit, preference.geq, status)));
+
+        converterPreferences_.emplaceBack(inputUnit, complexTargetUnit, preference.geq, conversionRates,
+                                          status);
     }
 }
 
index 0b06c86f7a6269deeaf24d2a64a846f74907e958..8fe7bb463b7bbbd7da7787807446d70e53d90746 100644 (file)
@@ -10,6 +10,7 @@
 #include "charstr.h" // CharString
 #include "cmemory.h"
 #include "complexunitsconverter.h"
+#include "getunitsdata.h"
 #include "unicode/errorcode.h"
 #include "unicode/measunit.h"
 #include "unicode/measure.h"
@@ -21,8 +22,9 @@ struct ConverterPreference {
     ComplexUnitsConverter converter;
     double limit;
 
-    ConverterPreference(MeasureUnit source, MeasureUnit complexTarget, double limit, UErrorCode &status)
-        : converter(source, complexTarget, status), limit(limit) {}
+    ConverterPreference(MeasureUnit source, MeasureUnit complexTarget, double limit,
+                        const MaybeStackVector<ConversionRateInfo> &ratesInfo, UErrorCode &status)
+        : converter(source, complexTarget, ratesInfo, status), limit(limit) {}
 };
 
 class U_I18N_API UnitsRouter {