xref: /aosp_15_r20/external/icu/libicu/cts_headers/units_router.h (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker // © 2020 and later: Unicode, Inc. and others.
2*0e209d39SAndroid Build Coastguard Worker // License & terms of use: http://www.unicode.org/copyright.html
3*0e209d39SAndroid Build Coastguard Worker 
4*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h"
5*0e209d39SAndroid Build Coastguard Worker 
6*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_FORMATTING
7*0e209d39SAndroid Build Coastguard Worker #ifndef __UNITS_ROUTER_H__
8*0e209d39SAndroid Build Coastguard Worker #define __UNITS_ROUTER_H__
9*0e209d39SAndroid Build Coastguard Worker 
10*0e209d39SAndroid Build Coastguard Worker #include <limits>
11*0e209d39SAndroid Build Coastguard Worker 
12*0e209d39SAndroid Build Coastguard Worker #include "cmemory.h"
13*0e209d39SAndroid Build Coastguard Worker #include "measunit_impl.h"
14*0e209d39SAndroid Build Coastguard Worker #include "unicode/locid.h"
15*0e209d39SAndroid Build Coastguard Worker #include "unicode/measunit.h"
16*0e209d39SAndroid Build Coastguard Worker #include "unicode/stringpiece.h"
17*0e209d39SAndroid Build Coastguard Worker #include "unicode/uobject.h"
18*0e209d39SAndroid Build Coastguard Worker #include "units_complexconverter.h"
19*0e209d39SAndroid Build Coastguard Worker #include "units_data.h"
20*0e209d39SAndroid Build Coastguard Worker 
21*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN
22*0e209d39SAndroid Build Coastguard Worker 
23*0e209d39SAndroid Build Coastguard Worker // Forward declarations
24*0e209d39SAndroid Build Coastguard Worker class Measure;
25*0e209d39SAndroid Build Coastguard Worker namespace number {
26*0e209d39SAndroid Build Coastguard Worker class Precision;
27*0e209d39SAndroid Build Coastguard Worker }
28*0e209d39SAndroid Build Coastguard Worker 
29*0e209d39SAndroid Build Coastguard Worker namespace units {
30*0e209d39SAndroid Build Coastguard Worker 
31*0e209d39SAndroid Build Coastguard Worker struct RouteResult : UMemory {
32*0e209d39SAndroid Build Coastguard Worker     // A list of measures: a single measure for single units, multiple measures
33*0e209d39SAndroid Build Coastguard Worker     // for mixed units.
34*0e209d39SAndroid Build Coastguard Worker     MaybeStackVector<Measure> measures;
35*0e209d39SAndroid Build Coastguard Worker 
36*0e209d39SAndroid Build Coastguard Worker     // The output unit for this RouteResult. This may be a MIXED unit - for
37*0e209d39SAndroid Build Coastguard Worker     // example: "yard-and-foot-and-inch", for which `measures` will have three
38*0e209d39SAndroid Build Coastguard Worker     // elements.
39*0e209d39SAndroid Build Coastguard Worker     MeasureUnitImpl outputUnit;
40*0e209d39SAndroid Build Coastguard Worker 
RouteResultRouteResult41*0e209d39SAndroid Build Coastguard Worker     RouteResult(MaybeStackVector<Measure> measures, MeasureUnitImpl outputUnit)
42*0e209d39SAndroid Build Coastguard Worker         : measures(std::move(measures)), outputUnit(std::move(outputUnit)) {}
43*0e209d39SAndroid Build Coastguard Worker };
44*0e209d39SAndroid Build Coastguard Worker 
45*0e209d39SAndroid Build Coastguard Worker /**
46*0e209d39SAndroid Build Coastguard Worker  * Contains the complex unit converter and the limit which representing the smallest value that the
47*0e209d39SAndroid Build Coastguard Worker  * converter should accept. For example, if the converter is converting to `foot+inch` and the limit
48*0e209d39SAndroid Build Coastguard Worker  * equals 3.0, thus means the converter should not convert to a value less than `3.0 feet`.
49*0e209d39SAndroid Build Coastguard Worker  *
50*0e209d39SAndroid Build Coastguard Worker  * NOTE:
51*0e209d39SAndroid Build Coastguard Worker  *    if the limit doest not has a value `i.e. (std::numeric_limits<double>::lowest())`, this mean there
52*0e209d39SAndroid Build Coastguard Worker  *    is no limit for the converter.
53*0e209d39SAndroid Build Coastguard Worker  */
54*0e209d39SAndroid Build Coastguard Worker struct ConverterPreference : UMemory {
55*0e209d39SAndroid Build Coastguard Worker     ComplexUnitsConverter converter;
56*0e209d39SAndroid Build Coastguard Worker     double limit;
57*0e209d39SAndroid Build Coastguard Worker     UnicodeString precision;
58*0e209d39SAndroid Build Coastguard Worker 
59*0e209d39SAndroid Build Coastguard Worker     // The output unit for this ConverterPreference. This may be a MIXED unit -
60*0e209d39SAndroid Build Coastguard Worker     // for example: "yard-and-foot-and-inch".
61*0e209d39SAndroid Build Coastguard Worker     MeasureUnitImpl targetUnit;
62*0e209d39SAndroid Build Coastguard Worker 
63*0e209d39SAndroid Build Coastguard Worker     // In case there is no limit, the limit will be -inf.
ConverterPreferenceConverterPreference64*0e209d39SAndroid Build Coastguard Worker     ConverterPreference(const MeasureUnitImpl &source, const MeasureUnitImpl &complexTarget,
65*0e209d39SAndroid Build Coastguard Worker                         UnicodeString precision, const ConversionRates &ratesInfo, UErrorCode &status)
66*0e209d39SAndroid Build Coastguard Worker         : ConverterPreference(source, complexTarget, std::numeric_limits<double>::lowest(), precision,
67*0e209d39SAndroid Build Coastguard Worker                               ratesInfo, status) {}
68*0e209d39SAndroid Build Coastguard Worker 
ConverterPreferenceConverterPreference69*0e209d39SAndroid Build Coastguard Worker     ConverterPreference(const MeasureUnitImpl &source, const MeasureUnitImpl &complexTarget,
70*0e209d39SAndroid Build Coastguard Worker                         double limit, UnicodeString precision, const ConversionRates &ratesInfo,
71*0e209d39SAndroid Build Coastguard Worker                         UErrorCode &status)
72*0e209d39SAndroid Build Coastguard Worker         : converter(source, complexTarget, ratesInfo, status), limit(limit),
73*0e209d39SAndroid Build Coastguard Worker           precision(std::move(precision)), targetUnit(complexTarget.copy(status)) {}
74*0e209d39SAndroid Build Coastguard Worker };
75*0e209d39SAndroid Build Coastguard Worker 
76*0e209d39SAndroid Build Coastguard Worker } // namespace units
77*0e209d39SAndroid Build Coastguard Worker 
78*0e209d39SAndroid Build Coastguard Worker // Export explicit template instantiations of MaybeStackArray, MemoryPool and
79*0e209d39SAndroid Build Coastguard Worker // MaybeStackVector. This is required when building DLLs for Windows. (See
80*0e209d39SAndroid Build Coastguard Worker // datefmt.h, collationiterator.h, erarules.h and others for similar examples.)
81*0e209d39SAndroid Build Coastguard Worker //
82*0e209d39SAndroid Build Coastguard Worker // Note: These need to be outside of the units namespace, or Clang will generate
83*0e209d39SAndroid Build Coastguard Worker // a compile error.
84*0e209d39SAndroid Build Coastguard Worker #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN
85*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackArray<units::ConverterPreference*, 8>;
86*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MemoryPool<units::ConverterPreference, 8>;
87*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackVector<units::ConverterPreference, 8>;
88*0e209d39SAndroid Build Coastguard Worker #endif
89*0e209d39SAndroid Build Coastguard Worker 
90*0e209d39SAndroid Build Coastguard Worker namespace units {
91*0e209d39SAndroid Build Coastguard Worker 
92*0e209d39SAndroid Build Coastguard Worker /**
93*0e209d39SAndroid Build Coastguard Worker  * `UnitsRouter` responsible for converting from a single unit (such as `meter` or `meter-per-second`) to
94*0e209d39SAndroid Build Coastguard Worker  * one of the complex units based on the limits.
95*0e209d39SAndroid Build Coastguard Worker  * For example:
96*0e209d39SAndroid Build Coastguard Worker  *    if the input is `meter` and the output as following
97*0e209d39SAndroid Build Coastguard Worker  *    {`foot+inch`, limit: 3.0}
98*0e209d39SAndroid Build Coastguard Worker  *    {`inch`     , limit: no value (-inf)}
99*0e209d39SAndroid Build Coastguard Worker  *    Thus means if the input in `meter` is greater than or equal to `3.0 feet`, the output will be in
100*0e209d39SAndroid Build Coastguard Worker  *    `foot+inch`, otherwise, the output will be in `inch`.
101*0e209d39SAndroid Build Coastguard Worker  *
102*0e209d39SAndroid Build Coastguard Worker  * NOTE:
103*0e209d39SAndroid Build Coastguard Worker  *    the output units and the their limits MUST BE in order, for example, if the output units, from the
104*0e209d39SAndroid Build Coastguard Worker  *    previous example, are the following:
105*0e209d39SAndroid Build Coastguard Worker  *        {`inch`     , limit: no value (-inf)}
106*0e209d39SAndroid Build Coastguard Worker  *        {`foot+inch`, limit: 3.0}
107*0e209d39SAndroid Build Coastguard Worker  *     IN THIS CASE THE OUTPUT WILL BE ALWAYS IN `inch`.
108*0e209d39SAndroid Build Coastguard Worker  *
109*0e209d39SAndroid Build Coastguard Worker  * NOTE:
110*0e209d39SAndroid Build Coastguard Worker  *    the output units  and their limits will be extracted from the units preferences database by knowing
111*0e209d39SAndroid Build Coastguard Worker  *    the following:
112*0e209d39SAndroid Build Coastguard Worker  *        - input unit
113*0e209d39SAndroid Build Coastguard Worker  *        - locale
114*0e209d39SAndroid Build Coastguard Worker  *        - usage
115*0e209d39SAndroid Build Coastguard Worker  *
116*0e209d39SAndroid Build Coastguard Worker  * DESIGN:
117*0e209d39SAndroid Build Coastguard Worker  *    `UnitRouter` uses internally `ComplexUnitConverter` in order to convert the input units to the
118*0e209d39SAndroid Build Coastguard Worker  *    desired complex units and to check the limit too.
119*0e209d39SAndroid Build Coastguard Worker  */
120*0e209d39SAndroid Build Coastguard Worker class U_I18N_API UnitsRouter {
121*0e209d39SAndroid Build Coastguard Worker   public:
122*0e209d39SAndroid Build Coastguard Worker     UnitsRouter(StringPiece inputUnitIdentifier, const Locale &locale, StringPiece usage,
123*0e209d39SAndroid Build Coastguard Worker                 UErrorCode &status);
124*0e209d39SAndroid Build Coastguard Worker     UnitsRouter(const MeasureUnit &inputUnit, const Locale &locale, StringPiece usage,
125*0e209d39SAndroid Build Coastguard Worker                 UErrorCode &status);
126*0e209d39SAndroid Build Coastguard Worker 
127*0e209d39SAndroid Build Coastguard Worker     /**
128*0e209d39SAndroid Build Coastguard Worker      * Performs locale and usage sensitive unit conversion.
129*0e209d39SAndroid Build Coastguard Worker      * @param quantity The quantity to convert, expressed in terms of inputUnit.
130*0e209d39SAndroid Build Coastguard Worker      * @param rounder If not null, this RoundingImpl will be used to do rounding
131*0e209d39SAndroid Build Coastguard Worker      *     on the converted value. If the rounder lacks an fPrecision, the
132*0e209d39SAndroid Build Coastguard Worker      *     rounder will be modified to use the preferred precision for the usage
133*0e209d39SAndroid Build Coastguard Worker      *     and locale preference, alternatively with the default precision.
134*0e209d39SAndroid Build Coastguard Worker      * @param status Receives status.
135*0e209d39SAndroid Build Coastguard Worker      */
136*0e209d39SAndroid Build Coastguard Worker     RouteResult route(double quantity, icu::number::impl::RoundingImpl *rounder, UErrorCode &status) const;
137*0e209d39SAndroid Build Coastguard Worker 
138*0e209d39SAndroid Build Coastguard Worker     /**
139*0e209d39SAndroid Build Coastguard Worker      * Returns the list of possible output units, i.e. the full set of
140*0e209d39SAndroid Build Coastguard Worker      * preferences, for the localized, usage-specific unit preferences.
141*0e209d39SAndroid Build Coastguard Worker      *
142*0e209d39SAndroid Build Coastguard Worker      * The returned pointer should be valid for the lifetime of the
143*0e209d39SAndroid Build Coastguard Worker      * UnitsRouter instance.
144*0e209d39SAndroid Build Coastguard Worker      */
145*0e209d39SAndroid Build Coastguard Worker     const MaybeStackVector<MeasureUnit> *getOutputUnits() const;
146*0e209d39SAndroid Build Coastguard Worker 
147*0e209d39SAndroid Build Coastguard Worker   private:
148*0e209d39SAndroid Build Coastguard Worker     // List of possible output units. TODO: converterPreferences_ now also has
149*0e209d39SAndroid Build Coastguard Worker     // this data available. Maybe drop outputUnits_ and have getOutputUnits
150*0e209d39SAndroid Build Coastguard Worker     // construct a the list from data in converterPreferences_ instead?
151*0e209d39SAndroid Build Coastguard Worker     MaybeStackVector<MeasureUnit> outputUnits_;
152*0e209d39SAndroid Build Coastguard Worker 
153*0e209d39SAndroid Build Coastguard Worker     MaybeStackVector<ConverterPreference> converterPreferences_;
154*0e209d39SAndroid Build Coastguard Worker 
155*0e209d39SAndroid Build Coastguard Worker     static number::Precision parseSkeletonToPrecision(icu::UnicodeString precisionSkeleton,
156*0e209d39SAndroid Build Coastguard Worker                                                       UErrorCode &status);
157*0e209d39SAndroid Build Coastguard Worker 
158*0e209d39SAndroid Build Coastguard Worker     void init(const MeasureUnit &inputUnit, const Locale &locale, StringPiece usage, UErrorCode &status);
159*0e209d39SAndroid Build Coastguard Worker };
160*0e209d39SAndroid Build Coastguard Worker 
161*0e209d39SAndroid Build Coastguard Worker } // namespace units
162*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END
163*0e209d39SAndroid Build Coastguard Worker 
164*0e209d39SAndroid Build Coastguard Worker #endif //__UNITS_ROUTER_H__
165*0e209d39SAndroid Build Coastguard Worker 
166*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */
167