From: Younies Mahmoud Date: Tue, 24 Mar 2020 13:05:01 +0000 (+0100) Subject: hook up the data to units router X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aa070ecfe5bfa57b80ccae9e76480b5f3e4f469a;p=icu hook up the data to units router --- diff --git a/icu4c/source/i18n/complexunitsconverter.cpp b/icu4c/source/i18n/complexunitsconverter.cpp index 6470eb9bd06..5a0a0879e74 100644 --- a/icu4c/source/i18n/complexunitsconverter.cpp +++ b/icu4c/source/i18n/complexunitsconverter.cpp @@ -11,10 +11,12 @@ #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 &ratesInfo, UErrorCode &status) { auto singleUnits = outputUnits.splitToSingleUnits(status); MaybeStackVector 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 outputUnits, + const MaybeStackVector &ratesInfo, UErrorCode &status) { if (outputUnits.length() == 0) { status = U_ILLEGAL_ARGUMENT_ERROR; @@ -37,10 +40,10 @@ ComplexUnitsConverter::ComplexUnitsConverter(const MeasureUnit inputUnit, MaybeStackVector 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; diff --git a/icu4c/source/i18n/complexunitsconverter.h b/icu4c/source/i18n/complexunitsconverter.h index bd9e0e6f7ca..e0bd4476504 100644 --- a/icu4c/source/i18n/complexunitsconverter.h +++ b/icu4c/source/i18n/complexunitsconverter.h @@ -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 outputUnits, - UErrorCode &status); + const MaybeStackVector &ratesInfo, UErrorCode &status); ComplexUnitsConverter(const MeasureUnit inputUnit, const MeasureUnit outputUnits, - UErrorCode &status); + const MaybeStackVector &ratesInfo, UErrorCode &status); // Returns true if the `quantity` in the `inputUnit` is greater than or equal than the `limit` in the // biggest `outputUnits` diff --git a/icu4c/source/i18n/getunitsdata.h b/icu4c/source/i18n/getunitsdata.h index da7ab68051a..cdfb77a25d1 100644 --- a/icu4c/source/i18n/getunitsdata.h +++ b/icu4c/source/i18n/getunitsdata.h @@ -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" @@ -17,14 +16,15 @@ 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 &conversionInfo, MaybeStackVector &unitPreferences, UErrorCode &status); +// TODO(hugo): Implement +MaybeStackVector + U_I18N_API getConversionRatesInfo(MeasureUnit source, MeasureUnit target, UErrorCode &status); + U_NAMESPACE_END #endif //__GETUNITSDATA_H__ diff --git a/icu4c/source/i18n/unitconverter.cpp b/icu4c/source/i18n/unitconverter.cpp index 65412848ebe..32761f4af35 100644 --- a/icu4c/source/i18n/unitconverter.cpp +++ b/icu4c/source/i18n/unitconverter.cpp @@ -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 &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 &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 &convertUnits, UErrorCode &status) { - auto conversionUnit = extractConvertUnit(source, convertUnits, status); + const MaybeStackVector &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 &convertUnits, UErrorCode &status) { + const MaybeStackVector &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 &convertUnits, + UnitsCase unitsCase, const MaybeStackVector &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 &convertUnits, +StringPiece getTarget(StringPiece source, const MaybeStackVector &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 &convertUnits, +MeasureUnit extractTarget(MeasureUnit source, const MaybeStackVector &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 &convertUnits, UErrorCode &status) { - MeasureUnit sourceTargetUnit = extractTarget(source, convertUnits, status); - MeasureUnit targetTargetUnit = extractTarget(target, convertUnits, status); + const MaybeStackVector &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 &convertUnits, UErrorCode &status) { - UnitsCase unitsCase = checkUnitsCase(source, target, convertUnits, status); + const MaybeStackVector &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) { diff --git a/icu4c/source/i18n/unitconverter.h b/icu4c/source/i18n/unitconverter.h index 5bd164440e7..9549f5ee383 100644 --- a/icu4c/source/i18n/unitconverter.h +++ b/icu4c/source/i18n/unitconverter.h @@ -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" @@ -16,24 +17,6 @@ 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& convertUnits, - UErrorCode &status); + UnitConverter(MeasureUnit source, MeasureUnit target, + const MaybeStackVector &ratesInfo, UErrorCode &status); /** * Convert a value in the source unit to another value in the target unit. diff --git a/icu4c/source/i18n/unitsrouter.cpp b/icu4c/source/i18n/unitsrouter.cpp index f727cfa1522..db6018c9f47 100644 --- a/icu4c/source/i18n/unitsrouter.cpp +++ b/icu4c/source/i18n/unitsrouter.cpp @@ -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); } } diff --git a/icu4c/source/i18n/unitsrouter.h b/icu4c/source/i18n/unitsrouter.h index 0b06c86f7a6..8fe7bb463b7 100644 --- a/icu4c/source/i18n/unitsrouter.h +++ b/icu4c/source/i18n/unitsrouter.h @@ -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 &ratesInfo, UErrorCode &status) + : converter(source, complexTarget, ratesInfo, status), limit(limit) {} }; class U_I18N_API UnitsRouter {