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 #ifndef __MEASUNIT_IMPL_H__ 5*0e209d39SAndroid Build Coastguard Worker #define __MEASUNIT_IMPL_H__ 6*0e209d39SAndroid Build Coastguard Worker 7*0e209d39SAndroid Build Coastguard Worker #include "unicode/utypes.h" 8*0e209d39SAndroid Build Coastguard Worker 9*0e209d39SAndroid Build Coastguard Worker #if !UCONFIG_NO_FORMATTING 10*0e209d39SAndroid Build Coastguard Worker 11*0e209d39SAndroid Build Coastguard Worker #include "unicode/measunit.h" 12*0e209d39SAndroid Build Coastguard Worker #include "cmemory.h" 13*0e209d39SAndroid Build Coastguard Worker #include "charstr.h" 14*0e209d39SAndroid Build Coastguard Worker 15*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN 16*0e209d39SAndroid Build Coastguard Worker 17*0e209d39SAndroid Build Coastguard Worker namespace number::impl { 18*0e209d39SAndroid Build Coastguard Worker class LongNameHandler; 19*0e209d39SAndroid Build Coastguard Worker } 20*0e209d39SAndroid Build Coastguard Worker 21*0e209d39SAndroid Build Coastguard Worker static const char16_t kDefaultCurrency[] = u"XXX"; 22*0e209d39SAndroid Build Coastguard Worker static const char kDefaultCurrency8[] = "XXX"; 23*0e209d39SAndroid Build Coastguard Worker 24*0e209d39SAndroid Build Coastguard Worker /** 25*0e209d39SAndroid Build Coastguard Worker * Looks up the "unitQuantity" (aka "type" or "category") of a base unit 26*0e209d39SAndroid Build Coastguard Worker * identifier. The category is returned via `result`, which must initially be 27*0e209d39SAndroid Build Coastguard Worker * empty. 28*0e209d39SAndroid Build Coastguard Worker * 29*0e209d39SAndroid Build Coastguard Worker * This only supports base units: other units must be resolved to base units 30*0e209d39SAndroid Build Coastguard Worker * before passing to this function, otherwise U_UNSUPPORTED_ERROR status may be 31*0e209d39SAndroid Build Coastguard Worker * returned. 32*0e209d39SAndroid Build Coastguard Worker * 33*0e209d39SAndroid Build Coastguard Worker * Categories are found in `unitQuantities` in the `units` resource (see 34*0e209d39SAndroid Build Coastguard Worker * `units.txt`). 35*0e209d39SAndroid Build Coastguard Worker */ 36*0e209d39SAndroid Build Coastguard Worker // TODO: make this function accepts any `MeasureUnit` as Java and move it to the `UnitsData` class. 37*0e209d39SAndroid Build Coastguard Worker CharString U_I18N_API getUnitQuantity(const MeasureUnitImpl &baseMeasureUnitImpl, UErrorCode &status); 38*0e209d39SAndroid Build Coastguard Worker 39*0e209d39SAndroid Build Coastguard Worker /** 40*0e209d39SAndroid Build Coastguard Worker * A struct representing a single unit (optional SI or binary prefix, and dimensionality). 41*0e209d39SAndroid Build Coastguard Worker */ 42*0e209d39SAndroid Build Coastguard Worker struct U_I18N_API SingleUnitImpl : public UMemory { 43*0e209d39SAndroid Build Coastguard Worker /** 44*0e209d39SAndroid Build Coastguard Worker * Gets a single unit from the MeasureUnit. If there are multiple single units, sets an error 45*0e209d39SAndroid Build Coastguard Worker * code and returns the base dimensionless unit. Parses if necessary. 46*0e209d39SAndroid Build Coastguard Worker */ 47*0e209d39SAndroid Build Coastguard Worker static SingleUnitImpl forMeasureUnit(const MeasureUnit& measureUnit, UErrorCode& status); 48*0e209d39SAndroid Build Coastguard Worker 49*0e209d39SAndroid Build Coastguard Worker /** Transform this SingleUnitImpl into a MeasureUnit, simplifying if possible. */ 50*0e209d39SAndroid Build Coastguard Worker MeasureUnit build(UErrorCode& status) const; 51*0e209d39SAndroid Build Coastguard Worker 52*0e209d39SAndroid Build Coastguard Worker /** 53*0e209d39SAndroid Build Coastguard Worker * Returns the "simple unit ID", without SI or dimensionality prefix: this 54*0e209d39SAndroid Build Coastguard Worker * instance may represent a square-kilometer, but only "meter" will be 55*0e209d39SAndroid Build Coastguard Worker * returned. 56*0e209d39SAndroid Build Coastguard Worker * 57*0e209d39SAndroid Build Coastguard Worker * The returned pointer points at memory that exists for the duration of the 58*0e209d39SAndroid Build Coastguard Worker * program's running. 59*0e209d39SAndroid Build Coastguard Worker */ 60*0e209d39SAndroid Build Coastguard Worker const char *getSimpleUnitID() const; 61*0e209d39SAndroid Build Coastguard Worker 62*0e209d39SAndroid Build Coastguard Worker /** 63*0e209d39SAndroid Build Coastguard Worker * Generates and append a neutral identifier string for a single unit which means we do not include 64*0e209d39SAndroid Build Coastguard Worker * the dimension signal. 65*0e209d39SAndroid Build Coastguard Worker */ 66*0e209d39SAndroid Build Coastguard Worker void appendNeutralIdentifier(CharString &result, UErrorCode &status) const; 67*0e209d39SAndroid Build Coastguard Worker 68*0e209d39SAndroid Build Coastguard Worker /** 69*0e209d39SAndroid Build Coastguard Worker * Returns the index of this unit's "quantity" in unitQuantities (in 70*0e209d39SAndroid Build Coastguard Worker * measunit_extra.cpp). The value of this index determines sort order for 71*0e209d39SAndroid Build Coastguard Worker * normalization of unit identifiers. 72*0e209d39SAndroid Build Coastguard Worker */ 73*0e209d39SAndroid Build Coastguard Worker int32_t getUnitCategoryIndex() const; 74*0e209d39SAndroid Build Coastguard Worker 75*0e209d39SAndroid Build Coastguard Worker /** 76*0e209d39SAndroid Build Coastguard Worker * Compare this SingleUnitImpl to another SingleUnitImpl for the sake of 77*0e209d39SAndroid Build Coastguard Worker * sorting and coalescing. 78*0e209d39SAndroid Build Coastguard Worker * 79*0e209d39SAndroid Build Coastguard Worker * Sort order of units is specified by UTS #35 80*0e209d39SAndroid Build Coastguard Worker * (https://unicode.org/reports/tr35/tr35-info.html#Unit_Identifier_Normalization). 81*0e209d39SAndroid Build Coastguard Worker * 82*0e209d39SAndroid Build Coastguard Worker * Takes the sign of dimensionality into account, but not the absolute 83*0e209d39SAndroid Build Coastguard Worker * value: per-meter is not considered the same as meter, but meter is 84*0e209d39SAndroid Build Coastguard Worker * considered the same as square-meter. 85*0e209d39SAndroid Build Coastguard Worker * 86*0e209d39SAndroid Build Coastguard Worker * The dimensionless unit generally does not get compared, but if it did, it 87*0e209d39SAndroid Build Coastguard Worker * would sort before other units by virtue of index being < 0 and 88*0e209d39SAndroid Build Coastguard Worker * dimensionality not being negative. 89*0e209d39SAndroid Build Coastguard Worker */ compareToSingleUnitImpl90*0e209d39SAndroid Build Coastguard Worker int32_t compareTo(const SingleUnitImpl& other) const { 91*0e209d39SAndroid Build Coastguard Worker if (dimensionality < 0 && other.dimensionality > 0) { 92*0e209d39SAndroid Build Coastguard Worker // Positive dimensions first 93*0e209d39SAndroid Build Coastguard Worker return 1; 94*0e209d39SAndroid Build Coastguard Worker } 95*0e209d39SAndroid Build Coastguard Worker if (dimensionality > 0 && other.dimensionality < 0) { 96*0e209d39SAndroid Build Coastguard Worker return -1; 97*0e209d39SAndroid Build Coastguard Worker } 98*0e209d39SAndroid Build Coastguard Worker 99*0e209d39SAndroid Build Coastguard Worker // Sort by official quantity order 100*0e209d39SAndroid Build Coastguard Worker int32_t thisQuantity = this->getUnitCategoryIndex(); 101*0e209d39SAndroid Build Coastguard Worker int32_t otherQuantity = other.getUnitCategoryIndex(); 102*0e209d39SAndroid Build Coastguard Worker if (thisQuantity < otherQuantity) { 103*0e209d39SAndroid Build Coastguard Worker return -1; 104*0e209d39SAndroid Build Coastguard Worker } 105*0e209d39SAndroid Build Coastguard Worker if (thisQuantity > otherQuantity) { 106*0e209d39SAndroid Build Coastguard Worker return 1; 107*0e209d39SAndroid Build Coastguard Worker } 108*0e209d39SAndroid Build Coastguard Worker 109*0e209d39SAndroid Build Coastguard Worker // If quantity order didn't help, then we go by index. 110*0e209d39SAndroid Build Coastguard Worker if (index < other.index) { 111*0e209d39SAndroid Build Coastguard Worker return -1; 112*0e209d39SAndroid Build Coastguard Worker } 113*0e209d39SAndroid Build Coastguard Worker if (index > other.index) { 114*0e209d39SAndroid Build Coastguard Worker return 1; 115*0e209d39SAndroid Build Coastguard Worker } 116*0e209d39SAndroid Build Coastguard Worker 117*0e209d39SAndroid Build Coastguard Worker // When comparing binary prefixes vs SI prefixes, instead of comparing the actual values, we can 118*0e209d39SAndroid Build Coastguard Worker // multiply the binary prefix power by 3 and compare the powers. if they are equal, we can can 119*0e209d39SAndroid Build Coastguard Worker // compare the bases. 120*0e209d39SAndroid Build Coastguard Worker // NOTE: this methodology will fail if the binary prefix more than or equal 98. 121*0e209d39SAndroid Build Coastguard Worker int32_t unitBase = umeas_getPrefixBase(unitPrefix); 122*0e209d39SAndroid Build Coastguard Worker int32_t otherUnitBase = umeas_getPrefixBase(other.unitPrefix); 123*0e209d39SAndroid Build Coastguard Worker 124*0e209d39SAndroid Build Coastguard Worker // Values for comparison purposes only. 125*0e209d39SAndroid Build Coastguard Worker int32_t unitPower = unitBase == 1024 /* Binary Prefix */ ? umeas_getPrefixPower(unitPrefix) * 3 126*0e209d39SAndroid Build Coastguard Worker : umeas_getPrefixPower(unitPrefix); 127*0e209d39SAndroid Build Coastguard Worker int32_t otherUnitPower = 128*0e209d39SAndroid Build Coastguard Worker otherUnitBase == 1024 /* Binary Prefix */ ? umeas_getPrefixPower(other.unitPrefix) * 3 129*0e209d39SAndroid Build Coastguard Worker : umeas_getPrefixPower(other.unitPrefix); 130*0e209d39SAndroid Build Coastguard Worker 131*0e209d39SAndroid Build Coastguard Worker // NOTE: if the unitPower is less than the other, 132*0e209d39SAndroid Build Coastguard Worker // we return 1 not -1. Thus because we want th sorting order 133*0e209d39SAndroid Build Coastguard Worker // for the bigger prefix to be before the smaller. 134*0e209d39SAndroid Build Coastguard Worker // Example: megabyte should come before kilobyte. 135*0e209d39SAndroid Build Coastguard Worker if (unitPower < otherUnitPower) { 136*0e209d39SAndroid Build Coastguard Worker return 1; 137*0e209d39SAndroid Build Coastguard Worker } 138*0e209d39SAndroid Build Coastguard Worker if (unitPower > otherUnitPower) { 139*0e209d39SAndroid Build Coastguard Worker return -1; 140*0e209d39SAndroid Build Coastguard Worker } 141*0e209d39SAndroid Build Coastguard Worker 142*0e209d39SAndroid Build Coastguard Worker if (unitBase < otherUnitBase) { 143*0e209d39SAndroid Build Coastguard Worker return 1; 144*0e209d39SAndroid Build Coastguard Worker } 145*0e209d39SAndroid Build Coastguard Worker if (unitBase > otherUnitBase) { 146*0e209d39SAndroid Build Coastguard Worker return -1; 147*0e209d39SAndroid Build Coastguard Worker } 148*0e209d39SAndroid Build Coastguard Worker 149*0e209d39SAndroid Build Coastguard Worker return 0; 150*0e209d39SAndroid Build Coastguard Worker } 151*0e209d39SAndroid Build Coastguard Worker 152*0e209d39SAndroid Build Coastguard Worker /** 153*0e209d39SAndroid Build Coastguard Worker * Return whether this SingleUnitImpl is compatible with another for the purpose of coalescing. 154*0e209d39SAndroid Build Coastguard Worker * 155*0e209d39SAndroid Build Coastguard Worker * Units with the same base unit and SI or binary prefix should match, except that they must also 156*0e209d39SAndroid Build Coastguard Worker * have the same dimensionality sign, such that we don't merge numerator and denominator. 157*0e209d39SAndroid Build Coastguard Worker */ isCompatibleWithSingleUnitImpl158*0e209d39SAndroid Build Coastguard Worker bool isCompatibleWith(const SingleUnitImpl& other) const { 159*0e209d39SAndroid Build Coastguard Worker return (compareTo(other) == 0); 160*0e209d39SAndroid Build Coastguard Worker } 161*0e209d39SAndroid Build Coastguard Worker 162*0e209d39SAndroid Build Coastguard Worker /** 163*0e209d39SAndroid Build Coastguard Worker * Returns true if this unit is the "dimensionless base unit", as produced 164*0e209d39SAndroid Build Coastguard Worker * by the MeasureUnit() default constructor. (This does not include the 165*0e209d39SAndroid Build Coastguard Worker * likes of concentrations or angles.) 166*0e209d39SAndroid Build Coastguard Worker */ isDimensionlessSingleUnitImpl167*0e209d39SAndroid Build Coastguard Worker bool isDimensionless() const { 168*0e209d39SAndroid Build Coastguard Worker return index == -1; 169*0e209d39SAndroid Build Coastguard Worker } 170*0e209d39SAndroid Build Coastguard Worker 171*0e209d39SAndroid Build Coastguard Worker /** 172*0e209d39SAndroid Build Coastguard Worker * Simple unit index, unique for every simple unit, -1 for the dimensionless 173*0e209d39SAndroid Build Coastguard Worker * unit. This is an index into a string list in measunit_extra.cpp, as 174*0e209d39SAndroid Build Coastguard Worker * loaded by SimpleUnitIdentifiersSink. 175*0e209d39SAndroid Build Coastguard Worker * 176*0e209d39SAndroid Build Coastguard Worker * The default value is -1, meaning the dimensionless unit: 177*0e209d39SAndroid Build Coastguard Worker * isDimensionless() will return true, until index is changed. 178*0e209d39SAndroid Build Coastguard Worker */ 179*0e209d39SAndroid Build Coastguard Worker int32_t index = -1; 180*0e209d39SAndroid Build Coastguard Worker 181*0e209d39SAndroid Build Coastguard Worker /** 182*0e209d39SAndroid Build Coastguard Worker * SI or binary prefix. 183*0e209d39SAndroid Build Coastguard Worker * 184*0e209d39SAndroid Build Coastguard Worker * This is ignored for the dimensionless unit. 185*0e209d39SAndroid Build Coastguard Worker */ 186*0e209d39SAndroid Build Coastguard Worker UMeasurePrefix unitPrefix = UMEASURE_PREFIX_ONE; 187*0e209d39SAndroid Build Coastguard Worker 188*0e209d39SAndroid Build Coastguard Worker /** 189*0e209d39SAndroid Build Coastguard Worker * Dimensionality. 190*0e209d39SAndroid Build Coastguard Worker * 191*0e209d39SAndroid Build Coastguard Worker * This is meaningless for the dimensionless unit. 192*0e209d39SAndroid Build Coastguard Worker */ 193*0e209d39SAndroid Build Coastguard Worker int32_t dimensionality = 1; 194*0e209d39SAndroid Build Coastguard Worker }; 195*0e209d39SAndroid Build Coastguard Worker 196*0e209d39SAndroid Build Coastguard Worker // Forward declaration 197*0e209d39SAndroid Build Coastguard Worker struct MeasureUnitImplWithIndex; 198*0e209d39SAndroid Build Coastguard Worker 199*0e209d39SAndroid Build Coastguard Worker // Export explicit template instantiations of MaybeStackArray, MemoryPool and 200*0e209d39SAndroid Build Coastguard Worker // MaybeStackVector. This is required when building DLLs for Windows. (See 201*0e209d39SAndroid Build Coastguard Worker // datefmt.h, collationiterator.h, erarules.h and others for similar examples.) 202*0e209d39SAndroid Build Coastguard Worker #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN 203*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackArray<SingleUnitImpl *, 8>; 204*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MemoryPool<SingleUnitImpl, 8>; 205*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackVector<SingleUnitImpl, 8>; 206*0e209d39SAndroid Build Coastguard Worker #endif 207*0e209d39SAndroid Build Coastguard Worker 208*0e209d39SAndroid Build Coastguard Worker /** 209*0e209d39SAndroid Build Coastguard Worker * Internal representation of measurement units. Capable of representing all complexities of units, 210*0e209d39SAndroid Build Coastguard Worker * including mixed and compound units. 211*0e209d39SAndroid Build Coastguard Worker */ 212*0e209d39SAndroid Build Coastguard Worker class U_I18N_API MeasureUnitImpl : public UMemory { 213*0e209d39SAndroid Build Coastguard Worker public: 214*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl() = default; 215*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl(MeasureUnitImpl &&other) = default; 216*0e209d39SAndroid Build Coastguard Worker // No copy constructor, use MeasureUnitImpl::copy() to make it explicit. 217*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl(const MeasureUnitImpl &other, UErrorCode &status) = delete; 218*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl(const SingleUnitImpl &singleUnit, UErrorCode &status); 219*0e209d39SAndroid Build Coastguard Worker 220*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl &operator=(MeasureUnitImpl &&other) noexcept = default; 221*0e209d39SAndroid Build Coastguard Worker 222*0e209d39SAndroid Build Coastguard Worker /** Extract the MeasureUnitImpl from a MeasureUnit. */ get(const MeasureUnit & measureUnit)223*0e209d39SAndroid Build Coastguard Worker static inline const MeasureUnitImpl *get(const MeasureUnit &measureUnit) { 224*0e209d39SAndroid Build Coastguard Worker return measureUnit.fImpl; 225*0e209d39SAndroid Build Coastguard Worker } 226*0e209d39SAndroid Build Coastguard Worker 227*0e209d39SAndroid Build Coastguard Worker /** 228*0e209d39SAndroid Build Coastguard Worker * Parse a unit identifier into a MeasureUnitImpl. 229*0e209d39SAndroid Build Coastguard Worker * 230*0e209d39SAndroid Build Coastguard Worker * @param identifier The unit identifier string. 231*0e209d39SAndroid Build Coastguard Worker * @param status Set if the identifier string is not valid. 232*0e209d39SAndroid Build Coastguard Worker * @return A newly parsed value object. Behaviour of this unit is 233*0e209d39SAndroid Build Coastguard Worker * unspecified if an error is returned via status. 234*0e209d39SAndroid Build Coastguard Worker */ 235*0e209d39SAndroid Build Coastguard Worker static MeasureUnitImpl forIdentifier(StringPiece identifier, UErrorCode& status); 236*0e209d39SAndroid Build Coastguard Worker 237*0e209d39SAndroid Build Coastguard Worker /** 238*0e209d39SAndroid Build Coastguard Worker * Extract the MeasureUnitImpl from a MeasureUnit, or parse if it is not present. 239*0e209d39SAndroid Build Coastguard Worker * 240*0e209d39SAndroid Build Coastguard Worker * @param measureUnit The source MeasureUnit. 241*0e209d39SAndroid Build Coastguard Worker * @param memory A place to write the new MeasureUnitImpl if parsing is required. 242*0e209d39SAndroid Build Coastguard Worker * @param status Set if an error occurs. 243*0e209d39SAndroid Build Coastguard Worker * @return A reference to either measureUnit.fImpl or memory. 244*0e209d39SAndroid Build Coastguard Worker */ 245*0e209d39SAndroid Build Coastguard Worker static const MeasureUnitImpl& forMeasureUnit( 246*0e209d39SAndroid Build Coastguard Worker const MeasureUnit& measureUnit, MeasureUnitImpl& memory, UErrorCode& status); 247*0e209d39SAndroid Build Coastguard Worker 248*0e209d39SAndroid Build Coastguard Worker /** 249*0e209d39SAndroid Build Coastguard Worker * Extract the MeasureUnitImpl from a MeasureUnit, or parse if it is not present. 250*0e209d39SAndroid Build Coastguard Worker * 251*0e209d39SAndroid Build Coastguard Worker * @param measureUnit The source MeasureUnit. 252*0e209d39SAndroid Build Coastguard Worker * @param status Set if an error occurs. 253*0e209d39SAndroid Build Coastguard Worker * @return A value object, either newly parsed or copied from measureUnit. 254*0e209d39SAndroid Build Coastguard Worker */ 255*0e209d39SAndroid Build Coastguard Worker static MeasureUnitImpl forMeasureUnitMaybeCopy( 256*0e209d39SAndroid Build Coastguard Worker const MeasureUnit& measureUnit, UErrorCode& status); 257*0e209d39SAndroid Build Coastguard Worker 258*0e209d39SAndroid Build Coastguard Worker /** 259*0e209d39SAndroid Build Coastguard Worker * Used for currency units. 260*0e209d39SAndroid Build Coastguard Worker */ forCurrencyCode(StringPiece currencyCode)261*0e209d39SAndroid Build Coastguard Worker static inline MeasureUnitImpl forCurrencyCode(StringPiece currencyCode) { 262*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl result; 263*0e209d39SAndroid Build Coastguard Worker UErrorCode localStatus = U_ZERO_ERROR; 264*0e209d39SAndroid Build Coastguard Worker result.identifier.append(currencyCode, localStatus); 265*0e209d39SAndroid Build Coastguard Worker // localStatus is not expected to fail since currencyCode should be 3 chars long 266*0e209d39SAndroid Build Coastguard Worker return result; 267*0e209d39SAndroid Build Coastguard Worker } 268*0e209d39SAndroid Build Coastguard Worker 269*0e209d39SAndroid Build Coastguard Worker /** Transform this MeasureUnitImpl into a MeasureUnit, simplifying if possible. */ 270*0e209d39SAndroid Build Coastguard Worker MeasureUnit build(UErrorCode& status) &&; 271*0e209d39SAndroid Build Coastguard Worker 272*0e209d39SAndroid Build Coastguard Worker /** 273*0e209d39SAndroid Build Coastguard Worker * Create a copy of this MeasureUnitImpl. Don't use copy constructor to make this explicit. 274*0e209d39SAndroid Build Coastguard Worker */ 275*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl copy(UErrorCode& status) const; 276*0e209d39SAndroid Build Coastguard Worker 277*0e209d39SAndroid Build Coastguard Worker /** 278*0e209d39SAndroid Build Coastguard Worker * Extracts the list of all the individual units inside the `MeasureUnitImpl` with their indices. 279*0e209d39SAndroid Build Coastguard Worker * For example: 280*0e209d39SAndroid Build Coastguard Worker * - if the `MeasureUnitImpl` is `foot-per-hour` 281*0e209d39SAndroid Build Coastguard Worker * it will return a list of 1 {(0, `foot-per-hour`)} 282*0e209d39SAndroid Build Coastguard Worker * - if the `MeasureUnitImpl` is `foot-and-inch` 283*0e209d39SAndroid Build Coastguard Worker * it will return a list of 2 {(0, `foot`), (1, `inch`)} 284*0e209d39SAndroid Build Coastguard Worker */ 285*0e209d39SAndroid Build Coastguard Worker MaybeStackVector<MeasureUnitImplWithIndex> 286*0e209d39SAndroid Build Coastguard Worker extractIndividualUnitsWithIndices(UErrorCode &status) const; 287*0e209d39SAndroid Build Coastguard Worker 288*0e209d39SAndroid Build Coastguard Worker /** Mutates this MeasureUnitImpl to take the reciprocal. */ 289*0e209d39SAndroid Build Coastguard Worker void takeReciprocal(UErrorCode& status); 290*0e209d39SAndroid Build Coastguard Worker 291*0e209d39SAndroid Build Coastguard Worker /** 292*0e209d39SAndroid Build Coastguard Worker * Returns a simplified version of the unit. 293*0e209d39SAndroid Build Coastguard Worker * NOTE: the simplification happen when there are two units equals in their base unit and their 294*0e209d39SAndroid Build Coastguard Worker * prefixes. 295*0e209d39SAndroid Build Coastguard Worker * 296*0e209d39SAndroid Build Coastguard Worker * Example 1: "square-meter-per-meter" --> "meter" 297*0e209d39SAndroid Build Coastguard Worker * Example 2: "square-millimeter-per-meter" --> "square-millimeter-per-meter" 298*0e209d39SAndroid Build Coastguard Worker */ 299*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl copyAndSimplify(UErrorCode &status) const; 300*0e209d39SAndroid Build Coastguard Worker 301*0e209d39SAndroid Build Coastguard Worker /** 302*0e209d39SAndroid Build Coastguard Worker * Mutates this MeasureUnitImpl to append a single unit. 303*0e209d39SAndroid Build Coastguard Worker * 304*0e209d39SAndroid Build Coastguard Worker * @return true if a new item was added. If unit is the dimensionless unit, 305*0e209d39SAndroid Build Coastguard Worker * it is never added: the return value will always be false. 306*0e209d39SAndroid Build Coastguard Worker */ 307*0e209d39SAndroid Build Coastguard Worker bool appendSingleUnit(const SingleUnitImpl& singleUnit, UErrorCode& status); 308*0e209d39SAndroid Build Coastguard Worker 309*0e209d39SAndroid Build Coastguard Worker /** 310*0e209d39SAndroid Build Coastguard Worker * Normalizes a MeasureUnitImpl and generate the identifier string in place. 311*0e209d39SAndroid Build Coastguard Worker */ 312*0e209d39SAndroid Build Coastguard Worker void serialize(UErrorCode &status); 313*0e209d39SAndroid Build Coastguard Worker 314*0e209d39SAndroid Build Coastguard Worker /** The complexity, either SINGLE, COMPOUND, or MIXED. */ 315*0e209d39SAndroid Build Coastguard Worker UMeasureUnitComplexity complexity = UMEASURE_UNIT_SINGLE; 316*0e209d39SAndroid Build Coastguard Worker 317*0e209d39SAndroid Build Coastguard Worker /** 318*0e209d39SAndroid Build Coastguard Worker * The list of single units. These may be summed or multiplied, based on the 319*0e209d39SAndroid Build Coastguard Worker * value of the complexity field. 320*0e209d39SAndroid Build Coastguard Worker * 321*0e209d39SAndroid Build Coastguard Worker * The "dimensionless" unit (SingleUnitImpl default constructor) must not be 322*0e209d39SAndroid Build Coastguard Worker * added to this list. 323*0e209d39SAndroid Build Coastguard Worker */ 324*0e209d39SAndroid Build Coastguard Worker MaybeStackVector<SingleUnitImpl> singleUnits; 325*0e209d39SAndroid Build Coastguard Worker 326*0e209d39SAndroid Build Coastguard Worker /** 327*0e209d39SAndroid Build Coastguard Worker * The full unit identifier. Owned by the MeasureUnitImpl. Empty if not computed. 328*0e209d39SAndroid Build Coastguard Worker */ 329*0e209d39SAndroid Build Coastguard Worker CharString identifier; 330*0e209d39SAndroid Build Coastguard Worker 331*0e209d39SAndroid Build Coastguard Worker // For calling serialize 332*0e209d39SAndroid Build Coastguard Worker // TODO(icu-units#147): revisit serialization 333*0e209d39SAndroid Build Coastguard Worker friend class number::impl::LongNameHandler; 334*0e209d39SAndroid Build Coastguard Worker }; 335*0e209d39SAndroid Build Coastguard Worker 336*0e209d39SAndroid Build Coastguard Worker struct U_I18N_API MeasureUnitImplWithIndex : public UMemory { 337*0e209d39SAndroid Build Coastguard Worker const int32_t index; 338*0e209d39SAndroid Build Coastguard Worker MeasureUnitImpl unitImpl; 339*0e209d39SAndroid Build Coastguard Worker // Makes a copy of unitImpl. MeasureUnitImplWithIndexMeasureUnitImplWithIndex340*0e209d39SAndroid Build Coastguard Worker MeasureUnitImplWithIndex(int32_t index, const MeasureUnitImpl &unitImpl, UErrorCode &status) 341*0e209d39SAndroid Build Coastguard Worker : index(index), unitImpl(unitImpl.copy(status)) { 342*0e209d39SAndroid Build Coastguard Worker } MeasureUnitImplWithIndexMeasureUnitImplWithIndex343*0e209d39SAndroid Build Coastguard Worker MeasureUnitImplWithIndex(int32_t index, const SingleUnitImpl &singleUnitImpl, UErrorCode &status) 344*0e209d39SAndroid Build Coastguard Worker : index(index), unitImpl(MeasureUnitImpl(singleUnitImpl, status)) { 345*0e209d39SAndroid Build Coastguard Worker } 346*0e209d39SAndroid Build Coastguard Worker }; 347*0e209d39SAndroid Build Coastguard Worker 348*0e209d39SAndroid Build Coastguard Worker // Export explicit template instantiations of MaybeStackArray, MemoryPool and 349*0e209d39SAndroid Build Coastguard Worker // MaybeStackVector. This is required when building DLLs for Windows. (See 350*0e209d39SAndroid Build Coastguard Worker // datefmt.h, collationiterator.h, erarules.h and others for similar examples.) 351*0e209d39SAndroid Build Coastguard Worker #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN 352*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackArray<MeasureUnitImplWithIndex *, 8>; 353*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MemoryPool<MeasureUnitImplWithIndex, 8>; 354*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API MaybeStackVector<MeasureUnitImplWithIndex, 8>; 355*0e209d39SAndroid Build Coastguard Worker 356*0e209d39SAndroid Build Coastguard Worker // Export an explicit template instantiation of the LocalPointer that is used as a 357*0e209d39SAndroid Build Coastguard Worker // data member of MeasureUnitImpl. 358*0e209d39SAndroid Build Coastguard Worker // (When building DLLs for Windows this is required.) 359*0e209d39SAndroid Build Coastguard Worker #if defined(_MSC_VER) 360*0e209d39SAndroid Build Coastguard Worker // Ignore warning 4661 as LocalPointerBase does not use operator== or operator!= 361*0e209d39SAndroid Build Coastguard Worker #pragma warning(push) 362*0e209d39SAndroid Build Coastguard Worker #pragma warning(disable : 4661) 363*0e209d39SAndroid Build Coastguard Worker #endif 364*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API LocalPointerBase<MeasureUnitImpl>; 365*0e209d39SAndroid Build Coastguard Worker template class U_I18N_API LocalPointer<MeasureUnitImpl>; 366*0e209d39SAndroid Build Coastguard Worker #if defined(_MSC_VER) 367*0e209d39SAndroid Build Coastguard Worker #pragma warning(pop) 368*0e209d39SAndroid Build Coastguard Worker #endif 369*0e209d39SAndroid Build Coastguard Worker #endif 370*0e209d39SAndroid Build Coastguard Worker 371*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END 372*0e209d39SAndroid Build Coastguard Worker 373*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */ 374*0e209d39SAndroid Build Coastguard Worker #endif //__MEASUNIT_IMPL_H__ 375