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.
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) {
// 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_;
+// © 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
#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