From a4519b94dd4850eabb9b4a61052af0c77c07bdd8 Mon Sep 17 00:00:00 2001 From: Younies Mahmoud Date: Tue, 9 Jun 2020 14:56:28 +0200 Subject: [PATCH] add the internal design documentation --- icu4c/source/i18n/complexunitsconverter.h | 12 +++++++ icu4c/source/i18n/unitconverter.h | 8 +++-- icu4c/source/i18n/unitsrouter.h | 44 +++++++++++++++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/icu4c/source/i18n/complexunitsconverter.h b/icu4c/source/i18n/complexunitsconverter.h index 3b71689416f..1034571b067 100644 --- a/icu4c/source/i18n/complexunitsconverter.h +++ b/icu4c/source/i18n/complexunitsconverter.h @@ -16,6 +16,15 @@ U_NAMESPACE_BEGIN +/** + * Convert from single unit to multiple/complex unit. For example, from `meter` to `foot+inch`. + * + * + * DESIGN: + * This class uses `UnitConverter` in order to perform the single converter (i.e. converters from a + * single unit to another single unit). Therefore, `ComplexUnitsConverter` class contains multiple + * instances of the `UnitConverter` to perform the conversion. + */ class U_I18N_API ComplexUnitsConverter { public: /** @@ -38,6 +47,9 @@ 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` + // For example, if the input unit is `meter` and the target unit is `foot+inch`. Therefore, this + // function will convert the `quantity` from `meter` to `foot`, then, it will compare the value in + // `foot` with the `limit`. UBool greaterThanOrEqual(double quantity, double limit) const; // Returns outputMeasures which is an array with the correspinding values. diff --git a/icu4c/source/i18n/unitconverter.h b/icu4c/source/i18n/unitconverter.h index fe664f21e50..61ed7f4e688 100644 --- a/icu4c/source/i18n/unitconverter.h +++ b/icu4c/source/i18n/unitconverter.h @@ -44,6 +44,10 @@ UnitsConvertibilityState U_I18N_API checkConvertibility(const MeasureUnit &sourc /** * Converts from a source `MeasureUnit` to a target `MeasureUnit`. + * + * NOTE: + * the source and the target must be singular such as `meter` to `mile` or `mile-per-second` to + * `kilometer-per-millisecond`. However, `foot+inch` is not permitted. */ class U_I18N_API UnitConverter : public UMemory { public: @@ -57,8 +61,8 @@ class U_I18N_API UnitConverter : public UMemory { * @param target represents the target unit. * @param status */ - UnitConverter(MeasureUnit source, MeasureUnit target, - const ConversionRates &ratesInfo, UErrorCode &status); + UnitConverter(MeasureUnit source, MeasureUnit target, const ConversionRates &ratesInfo, + UErrorCode &status); /** * Convert a value in the source unit to another value in the target unit. diff --git a/icu4c/source/i18n/unitsrouter.h b/icu4c/source/i18n/unitsrouter.h index 9e38f150569..1b29d9d8f3a 100644 --- a/icu4c/source/i18n/unitsrouter.h +++ b/icu4c/source/i18n/unitsrouter.h @@ -7,6 +7,8 @@ #ifndef __UNITSROUTER_H__ #define __UNITSROUTER_H__ +#include + #include "charstr.h" // CharString #include "cmemory.h" #include "complexunitsconverter.h" @@ -18,6 +20,15 @@ U_NAMESPACE_BEGIN +/** + * Contains the complex unit converter and the limit which representing the smallest value that the + * converter should accept. For example, if the converter is converting to `foot+inch` and the limit + * equals 3.0, thus means the converter should not convert to a value less than `3.0 feet`. + * + * NOTE: + * if the limit doest not has a value `i.e. (std::numeric_limits::lowest())`, this mean there + * is no limit for the converter. + */ struct ConverterPreference : UMemory { ComplexUnitsConverter converter; double limit; @@ -25,8 +36,41 @@ struct ConverterPreference : UMemory { ConverterPreference(MeasureUnit source, MeasureUnit complexTarget, double limit, const ConversionRates &ratesInfo, UErrorCode &status) : converter(source, complexTarget, ratesInfo, status), limit(limit) {} + + ConverterPreference(MeasureUnit source, MeasureUnit complexTarget, const ConversionRates &ratesInfo, + UErrorCode &status) + : ConverterPreference(source, complexTarget, std::numeric_limits::lowest(), ratesInfo, + status) {} }; +/** + * `UnitsRouter` responsible for converting from a single unit (such as `meter` or `meter-per-second`) to + * one of the complex units based on the limits. + * For example: + * if the input is `meter` and the output as following + * {`foot+inch`, limit: 3.0} + * {`inch` , limit: no value (-inf)} + * Thus means if the input in `meter` is greater than or equal to `3.0 feet`, the output will be in + * `foot+inch`, otherwise, the output will be in `inch`. + * + * NOTE: + * the output units and the their limits MUST BE in order, for example, if the output units, from the + * previous example, are the following: + * {`inch` , limit: no value (-inf)} + * {`foot+inch`, limit: 3.0} + * IN THIS CASE THE OUTPUT WILL BE ALWAYS IN `inch`. + * + * NOTE: + * the output units and their limits will be extracted from the units preferences database by knowing + * the followings: + * - input unit + * - locale + * - usage + * + * DESIGN: + * `UnitRouter` uses internally `ComplexUnitConverter` in order to convert the input units to the + * desired complex units and to check the limit too. + */ class U_I18N_API UnitsRouter { public: UnitsRouter(MeasureUnit inputUnit, StringPiece locale, StringPiece usage, UErrorCode &status); -- 2.40.0