From: Younies Mahmoud Date: Tue, 17 Mar 2020 00:08:57 +0000 (+0100) Subject: implement units router X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fdb6d7d033827d7bb14b3409945566ebfec50c61;p=icu implement units router --- diff --git a/icu4c/source/i18n/complexunitsconverter.cpp b/icu4c/source/i18n/complexunitsconverter.cpp index f58a69d04d1..2d2a7fa7a10 100644 --- a/icu4c/source/i18n/complexunitsconverter.cpp +++ b/icu4c/source/i18n/complexunitsconverter.cpp @@ -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 ComplexUnitsConverter::convert(double quantity, UErrorCode &status) { +MaybeStackVector ComplexUnitsConverter::convert(double quantity, UErrorCode &status) const{ MaybeStackVector result; for (int i = 0, n = unitConverters_.length(); i < n; ++i) { diff --git a/icu4c/source/i18n/complexunitsconverter.h b/icu4c/source/i18n/complexunitsconverter.h index 27c6ecf9978..d13de5bf3b1 100644 --- a/icu4c/source/i18n/complexunitsconverter.h +++ b/icu4c/source/i18n/complexunitsconverter.h @@ -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 convert(double quantity, UErrorCode &status); + // the smallest element is the only element that has fractional values. + MaybeStackVector convert(double quantity, UErrorCode &status) const; private: MaybeStackVector unitConverters_; diff --git a/icu4c/source/i18n/unitsrouter.cpp b/icu4c/source/i18n/unitsrouter.cpp index e69de29bb2d..9da50ef0647 100644 --- a/icu4c/source/i18n/unitsrouter.cpp +++ b/icu4c/source/i18n/unitsrouter.cpp @@ -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 extractUnitPreferences(StringPiece locale, StringPiece usage, + StringPiece category) { + MaybeStackVector 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 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 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 diff --git a/icu4c/source/i18n/unitsrouter.h b/icu4c/source/i18n/unitsrouter.h index 6d7abf5d41d..4fb9e9cdb89 100644 --- a/icu4c/source/i18n/unitsrouter.h +++ b/icu4c/source/i18n/unitsrouter.h @@ -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" @@ -14,16 +16,22 @@ 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 route(double quantity, UErrorCode &status); + MaybeStackVector route(double quantity, UErrorCode &status); private: - LocalArray unitsConverters; + MaybeStackVector converterPreferences_; }; U_NAMESPACE_END