tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

units_complexconverter.h (5489B)


      1 // © 2020 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 
      4 #include "unicode/utypes.h"
      5 
      6 #if !UCONFIG_NO_FORMATTING
      7 #ifndef __UNITS_COMPLEXCONVERTER_H__
      8 #define __UNITS_COMPLEXCONVERTER_H__
      9 
     10 #include "cmemory.h"
     11 #include "measunit_impl.h"
     12 #include "number_roundingutils.h"
     13 #include "unicode/errorcode.h"
     14 #include "unicode/measure.h"
     15 #include "units_converter.h"
     16 #include "units_data.h"
     17 
     18 U_NAMESPACE_BEGIN
     19 
     20 namespace units {
     21 
     22 /**
     23 *  Converts from single or compound unit to single, compound or mixed units.
     24 * For example, from `meter` to `foot+inch`.
     25 *
     26 *  DESIGN:
     27 *    This class uses `UnitsConverter` in order to perform the single converter (i.e. converters from a
     28 *    single unit to another single unit). Therefore, `ComplexUnitsConverter` class contains multiple
     29 *    instances of the `UnitsConverter` to perform the conversion.
     30 */
     31 class U_I18N_API_CLASS ComplexUnitsConverter : public UMemory {
     32  public:
     33    /**
     34     * Constructs `ComplexUnitsConverter` for an `targetUnit` that could be Single, Compound or Mixed.
     35     * In case of:
     36     * 1- Single and Compound units,
     37     *    the conversion will not perform anything, the input will be equal to the output.
     38     * 2- Mixed Unit
     39     *    the conversion will consider the input is the biggest unit. And will convert it to be spread
     40     *    through the target units. For example: if target unit is "inch-and-foot", and the input is 2.5.
     41     *    The converter will consider the input value in "foot", because foot is the biggest unit.
     42     *    Then, it will convert 2.5 feet to "inch-and-foot".
     43     *
     44     * @param targetUnit could be any units type (single, compound or mixed).
     45     * @param ratesInfo
     46     * @param status
     47     */
     48    ComplexUnitsConverter(const MeasureUnitImpl &targetUnit, const ConversionRates &ratesInfo,
     49                          UErrorCode &status);
     50    /**
     51     * Constructor of `ComplexUnitsConverter`.
     52     * NOTE:
     53     *   - inputUnit and outputUnits must be under the same category
     54     *      - e.g. meter to feet and inches --> all of them are length units.
     55     *
     56     * @param inputUnit represents the source unit. (should be single or compound unit).
     57     * @param outputUnits represents the output unit. could be any type. (single, compound or mixed).
     58     * @param status
     59     */
     60    U_I18N_API ComplexUnitsConverter(StringPiece inputUnitIdentifier,
     61                                     StringPiece outputUnitsIdentifier,
     62                                     UErrorCode &status);
     63 
     64    /**
     65     * Constructor of `ComplexUnitsConverter`.
     66     * NOTE:
     67     *   - inputUnit and outputUnits must be under the same category
     68     *      - e.g. meter to feet and inches --> all of them are length units.
     69     *
     70     * @param inputUnit represents the source unit. (should be single or compound unit).
     71     * @param outputUnits represents the output unit. could be any type. (single, compound or mixed).
     72     * @param ratesInfo a ConversionRates instance containing the unit conversion rates.
     73     * @param status
     74     */
     75    U_I18N_API ComplexUnitsConverter(const MeasureUnitImpl &inputUnit,
     76                                     const MeasureUnitImpl &outputUnits,
     77                                     const ConversionRates &ratesInfo,
     78                                     UErrorCode &status);
     79 
     80    // Returns true if the specified `quantity` of the `inputUnit`, expressed in terms of the biggest
     81    // unit in the MeasureUnit `outputUnit`, is greater than or equal to `limit`.
     82    //    For example, if the input unit is `meter` and the target unit is `foot+inch`. Therefore, this
     83    //    function will convert the `quantity` from `meter` to `foot`, then, it will compare the value in
     84    //    `foot` with the `limit`.
     85    UBool greaterThanOrEqual(double quantity, double limit) const;
     86 
     87    // Returns outputMeasures which is an array with the corresponding values.
     88    //    - E.g. converting meters to feet and inches.
     89    //                  1 meter --> 3 feet, 3.3701 inches
     90    //         NOTE:
     91    //           the smallest element is the only element that could have fractional values. And all
     92    //           other elements are floored to the nearest integer
     93    U_I18N_API MaybeStackVector<Measure>
     94    convert(double quantity, icu::number::impl::RoundingImpl *rounder, UErrorCode &status) const;
     95 
     96    // TODO(ICU-21937): Make it private after submitting the public units conversion API.
     97    MaybeStackVector<UnitsConverter> unitsConverters_;
     98 
     99    // TODO(ICU-21937): Make it private after submitting the public units conversion API.
    100    // Individual units of mixed units, sorted big to small, with indices
    101    // indicating the requested output mixed unit order.
    102    MaybeStackVector<MeasureUnitImplWithIndex> units_;
    103 
    104  private:
    105    // Sorts units_, which must be populated before calling this, and populates
    106    // unitsConverters_.
    107    void init(const MeasureUnitImpl &inputUnit, const ConversionRates &ratesInfo, UErrorCode &status);
    108 
    109    // Applies the rounder to the quantity (last element) and bubble up any carried value to all the
    110    // intValues.
    111    // TODO(ICU-21288): get smarter about precision for mixed units.
    112    void applyRounder(MaybeStackArray<int64_t, 5> &intValues, double &quantity,
    113                      icu::number::impl::RoundingImpl *rounder, UErrorCode &status) const;
    114 };
    115 
    116 } // namespace units
    117 U_NAMESPACE_END
    118 
    119 #endif //__UNITS_COMPLEXCONVERTER_H__
    120 
    121 #endif /* #if !UCONFIG_NO_FORMATTING */