]> granicus.if.org Git - icu/commitdiff
implement units router
authorYounies Mahmoud <younies.mahmoud@gmail.com>
Tue, 17 Mar 2020 00:08:57 +0000 (01:08 +0100)
committerYounies Mahmoud <younies.mahmoud@gmail.com>
Tue, 17 Mar 2020 00:08:57 +0000 (01:08 +0100)
icu4c/source/i18n/complexunitsconverter.cpp
icu4c/source/i18n/complexunitsconverter.h
icu4c/source/i18n/unitsrouter.cpp
icu4c/source/i18n/unitsrouter.h

index f58a69d04d1613a6194d031476bc0791bbfe3d88..2d2a7fa7a10843815c68e96b3d3828ed7e0c6f94 100644 (file)
@@ -39,7 +39,7 @@ ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnit inputUnit,
     units_.appendAll(outputUnits, status);
 }
 
-UBool ComplexUnitsConverter::greaterThanOrEqual(double quantity, double limit) {
+UBool ComplexUnitsConverter::greaterThanOrEqual(double quantity, double limit) const{
     U_ASSERT(unitConverters_.length() ?> 0);
 
     // first quantity is the biggest one.
@@ -48,7 +48,7 @@ UBool ComplexUnitsConverter::greaterThanOrEqual(double quantity, double limit) {
     return newQuantity >= limit;
 }
 
-MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity, UErrorCode &status) {
+MaybeStackVector<Measure> ComplexUnitsConverter::convert(double quantity, UErrorCode &status) const{
     MaybeStackVector<Measure> result;
 
     for (int i = 0, n = unitConverters_.length(); i < n; ++i) {
index 27c6ecf99785c50892e0e64250bdc19bb667a383..d13de5bf3b1d75ea17d3f95e08ef199f87d5853e 100644 (file)
@@ -35,14 +35,14 @@ class U_I18N_API ComplexUnitsConverter {
 
     // 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);
+    UBool greaterThanOrEqual(double quantity, double limit) const;
 
     // 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);
+    //           the smallest element is the only element that has fractional values.
+    MaybeStackVector<Measure> convert(double quantity, UErrorCode &status) const;
 
   private:
     MaybeStackVector<UnitConverter> unitConverters_;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9da50ef06474c43b8583e0ec52627a3c7d1b0aad 100644 (file)
@@ -0,0 +1,74 @@
+// © 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 "unitsrouter.h"
+
+U_NAMESPACE_BEGIN
+
+namespace {
+/* Internal Data */
+// Preference of a single unit.
+struct UnitPreference {
+    StringPiece identifier;
+
+    // Represents the limit of the largest unit in the identifier that the quantity must be greater than
+    // or equal.
+    // e.g. geq: 0.3 for a unit "foot-and-inch"
+    double limit;
+};
+
+MaybeStackVector<UnitPreference> extractUnitPreferences(StringPiece locale, StringPiece usage,
+                                                        StringPiece category) {
+    MaybeStackVector<UnitPreference> result;
+
+    // TODO(hugovdm): extract from the database all the UnitPreference for the `locale`, `category` and
+    // `usage` in order.
+
+    return result;
+}
+
+StringPiece extractUnitCategory(MeasureUnit unit) {
+    StringPiece result;
+
+    // TODO(hugovdm): extract the category of a unit from their MeasureUnits.
+
+    return result;
+}
+
+} // namespace
+
+UnitsRouter::UnitsRouter(MeasureUnit inputUnit, StringPiece locale, StringPiece usage,
+                         UErrorCode &status) {
+    StringPiece unitCategory = extractUnitCategory(inputUnit);
+    MaybeStackVector<UnitPreference> preferences = extractUnitPreferences(locale, usage, unitCategory);
+
+    for (int i = 0, n = preferences.length(); i < n; ++i) {
+        const auto &preference = *preferences[i];
+        MeasureUnit complexTargetUnit = MeasureUnit::forIdentifier(preference.identifier, status);
+        converterPreferences_.emplaceBack(
+            ConverterPreference(inputUnit, complexTargetUnit, preference.limit, status));
+    }
+}
+
+MaybeStackVector<Measure> UnitsRouter::route(double quantity, UErrorCode &status) {
+    for (int i = 0, n = converterPreferences_.length(); i < n; i++) {
+        const auto &converterPreference = *converterPreferences_[i];
+
+        if (i == n - 1) { // last unit preference
+            return converterPreference.converter.convert(quantity, status);
+        }
+
+        if (converterPreference.converter.greaterThanOrEqual(quantity, converterPreference.limit)) {
+            return converterPreference.converter.convert(quantity, status);
+        }
+    }
+}
+
+U_NAMESPACE_END
+
+#endif /* #if !UCONFIG_NO_FORMATTING */
\ No newline at end of file
index 6d7abf5d41d902e7b20efb865abef26de7fdf052..4fb9e9cdb8993703fcd05535bed0233d412f80d7 100644 (file)
@@ -7,6 +7,8 @@
 #ifndef __UNITSROUTER_H__
 #define __UNITSROUTER_H__
 
+#include "cmemory.h"
+#include "complexunitsconverter.h"
 #include "unicode/errorcode.h"
 #include "unicode/measunit.h"
 #include "unicode/measure.h"
 
 U_NAMESPACE_BEGIN
 
-class UnitConverter;
+struct ConverterPreference {
+    ComplexUnitsConverter converter;
+    double limit;
+
+    ConverterPreference(MeasureUnit source, MeasureUnit complexTarget, double limit, UErrorCode &status)
+        : converter(source, complexTarget, status), limit(limit) {}
+};
 
 class U_I18N_API UnitsRouter {
   public:
-    UnitsRouter(MeasureUnit inputUnit, Locale locale, StringPiece usage);
+    UnitsRouter(MeasureUnit inputUnit, StringPiece locale, StringPiece usage, UErrorCode& status);
 
-    LocalArray<Measure> route(double quantity, UErrorCode &status);
+    MaybeStackVector<Measure> route(double quantity, UErrorCode &status);
 
   private:
-    LocalArray<UnitConverter> unitsConverters;
+    MaybeStackVector<ConverterPreference> converterPreferences_;
 };
 
 U_NAMESPACE_END