1*0e209d39SAndroid Build Coastguard Worker // © 2017 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 __NUMBER_LONGNAMES_H__ 8*0e209d39SAndroid Build Coastguard Worker #define __NUMBER_LONGNAMES_H__ 9*0e209d39SAndroid Build Coastguard Worker 10*0e209d39SAndroid Build Coastguard Worker #include "cmemory.h" 11*0e209d39SAndroid Build Coastguard Worker #include "unicode/listformatter.h" 12*0e209d39SAndroid Build Coastguard Worker #include "unicode/uversion.h" 13*0e209d39SAndroid Build Coastguard Worker #include "number_utils.h" 14*0e209d39SAndroid Build Coastguard Worker #include "number_modifiers.h" 15*0e209d39SAndroid Build Coastguard Worker 16*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_BEGIN 17*0e209d39SAndroid Build Coastguard Worker namespace number::impl { 18*0e209d39SAndroid Build Coastguard Worker 19*0e209d39SAndroid Build Coastguard Worker // LongNameHandler takes care of formatting currency and measurement unit names, 20*0e209d39SAndroid Build Coastguard Worker // as well as populating the gender of measure units. 21*0e209d39SAndroid Build Coastguard Worker class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory { 22*0e209d39SAndroid Build Coastguard Worker public: 23*0e209d39SAndroid Build Coastguard Worker static UnicodeString getUnitDisplayName( 24*0e209d39SAndroid Build Coastguard Worker const Locale& loc, 25*0e209d39SAndroid Build Coastguard Worker const MeasureUnit& unit, 26*0e209d39SAndroid Build Coastguard Worker UNumberUnitWidth width, 27*0e209d39SAndroid Build Coastguard Worker UErrorCode& status); 28*0e209d39SAndroid Build Coastguard Worker 29*0e209d39SAndroid Build Coastguard Worker // This function does not support inflections or other newer NumberFormatter 30*0e209d39SAndroid Build Coastguard Worker // features: it exists to support the older not-recommended MeasureFormat. 31*0e209d39SAndroid Build Coastguard Worker static UnicodeString getUnitPattern( 32*0e209d39SAndroid Build Coastguard Worker const Locale& loc, 33*0e209d39SAndroid Build Coastguard Worker const MeasureUnit& unit, 34*0e209d39SAndroid Build Coastguard Worker UNumberUnitWidth width, 35*0e209d39SAndroid Build Coastguard Worker StandardPlural::Form pluralForm, 36*0e209d39SAndroid Build Coastguard Worker UErrorCode& status); 37*0e209d39SAndroid Build Coastguard Worker 38*0e209d39SAndroid Build Coastguard Worker static LongNameHandler* 39*0e209d39SAndroid Build Coastguard Worker forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules, 40*0e209d39SAndroid Build Coastguard Worker const MicroPropsGenerator *parent, UErrorCode &status); 41*0e209d39SAndroid Build Coastguard Worker 42*0e209d39SAndroid Build Coastguard Worker /** 43*0e209d39SAndroid Build Coastguard Worker * Construct a localized LongNameHandler for the specified MeasureUnit. 44*0e209d39SAndroid Build Coastguard Worker * 45*0e209d39SAndroid Build Coastguard Worker * Mixed units are not supported, use MixedUnitLongNameHandler::forMeasureUnit. 46*0e209d39SAndroid Build Coastguard Worker * 47*0e209d39SAndroid Build Coastguard Worker * This function uses a fillIn instead of returning a pointer, because we 48*0e209d39SAndroid Build Coastguard Worker * want to fill in instances in a MemoryPool (which cannot adopt pointers it 49*0e209d39SAndroid Build Coastguard Worker * didn't create itself). 50*0e209d39SAndroid Build Coastguard Worker * 51*0e209d39SAndroid Build Coastguard Worker * @param loc The desired locale. 52*0e209d39SAndroid Build Coastguard Worker * @param unitRef The measure unit to construct a LongNameHandler for. 53*0e209d39SAndroid Build Coastguard Worker * @param width Specifies the desired unit rendering. 54*0e209d39SAndroid Build Coastguard Worker * @param unitDisplayCase Specifies the desired grammatical case. If the 55*0e209d39SAndroid Build Coastguard Worker * specified case is not found, we fall back to nominative or no-case. 56*0e209d39SAndroid Build Coastguard Worker * @param rules Does not take ownership. 57*0e209d39SAndroid Build Coastguard Worker * @param parent Does not take ownership. 58*0e209d39SAndroid Build Coastguard Worker * @param fillIn Required. 59*0e209d39SAndroid Build Coastguard Worker */ 60*0e209d39SAndroid Build Coastguard Worker static void forMeasureUnit(const Locale &loc, 61*0e209d39SAndroid Build Coastguard Worker const MeasureUnit &unitRef, 62*0e209d39SAndroid Build Coastguard Worker const UNumberUnitWidth &width, 63*0e209d39SAndroid Build Coastguard Worker const char *unitDisplayCase, 64*0e209d39SAndroid Build Coastguard Worker const PluralRules *rules, 65*0e209d39SAndroid Build Coastguard Worker const MicroPropsGenerator *parent, 66*0e209d39SAndroid Build Coastguard Worker LongNameHandler *fillIn, 67*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 68*0e209d39SAndroid Build Coastguard Worker 69*0e209d39SAndroid Build Coastguard Worker /** 70*0e209d39SAndroid Build Coastguard Worker * Selects the plural-appropriate Modifier from the set of fModifiers based 71*0e209d39SAndroid Build Coastguard Worker * on the plural form. 72*0e209d39SAndroid Build Coastguard Worker */ 73*0e209d39SAndroid Build Coastguard Worker void 74*0e209d39SAndroid Build Coastguard Worker processQuantity(DecimalQuantity &quantity, MicroProps µs, UErrorCode &status) const override; 75*0e209d39SAndroid Build Coastguard Worker 76*0e209d39SAndroid Build Coastguard Worker const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const override; 77*0e209d39SAndroid Build Coastguard Worker 78*0e209d39SAndroid Build Coastguard Worker private: 79*0e209d39SAndroid Build Coastguard Worker // A set of pre-computed modifiers, one for each plural form. 80*0e209d39SAndroid Build Coastguard Worker SimpleModifier fModifiers[StandardPlural::Form::COUNT]; 81*0e209d39SAndroid Build Coastguard Worker // Not owned 82*0e209d39SAndroid Build Coastguard Worker const PluralRules *rules; 83*0e209d39SAndroid Build Coastguard Worker // Not owned 84*0e209d39SAndroid Build Coastguard Worker const MicroPropsGenerator *parent; 85*0e209d39SAndroid Build Coastguard Worker // Grammatical gender of the formatted result. Not owned: must point at 86*0e209d39SAndroid Build Coastguard Worker // static or global strings. 87*0e209d39SAndroid Build Coastguard Worker const char *gender = ""; 88*0e209d39SAndroid Build Coastguard Worker LongNameHandler(const PluralRules * rules,const MicroPropsGenerator * parent)89*0e209d39SAndroid Build Coastguard Worker LongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent) 90*0e209d39SAndroid Build Coastguard Worker : rules(rules), parent(parent) { 91*0e209d39SAndroid Build Coastguard Worker } 92*0e209d39SAndroid Build Coastguard Worker LongNameHandler()93*0e209d39SAndroid Build Coastguard Worker LongNameHandler() : rules(nullptr), parent(nullptr) { 94*0e209d39SAndroid Build Coastguard Worker } 95*0e209d39SAndroid Build Coastguard Worker 96*0e209d39SAndroid Build Coastguard Worker // Enables MemoryPool<LongNameHandler>::emplaceBack(): requires access to 97*0e209d39SAndroid Build Coastguard Worker // the private constructors. 98*0e209d39SAndroid Build Coastguard Worker friend class MemoryPool<LongNameHandler>; 99*0e209d39SAndroid Build Coastguard Worker 100*0e209d39SAndroid Build Coastguard Worker // Allow macrosToMicroGenerator to call the private default constructor. 101*0e209d39SAndroid Build Coastguard Worker friend class NumberFormatterImpl; 102*0e209d39SAndroid Build Coastguard Worker 103*0e209d39SAndroid Build Coastguard Worker // Fills in LongNameHandler fields for formatting units identified `unit`. 104*0e209d39SAndroid Build Coastguard Worker static void forArbitraryUnit(const Locale &loc, 105*0e209d39SAndroid Build Coastguard Worker const MeasureUnit &unit, 106*0e209d39SAndroid Build Coastguard Worker const UNumberUnitWidth &width, 107*0e209d39SAndroid Build Coastguard Worker const char *unitDisplayCase, 108*0e209d39SAndroid Build Coastguard Worker LongNameHandler *fillIn, 109*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 110*0e209d39SAndroid Build Coastguard Worker 111*0e209d39SAndroid Build Coastguard Worker // Roughly corresponds to patternTimes(...) in the spec: 112*0e209d39SAndroid Build Coastguard Worker // https://unicode.org/reports/tr35/tr35-general.html#compound-units 113*0e209d39SAndroid Build Coastguard Worker // 114*0e209d39SAndroid Build Coastguard Worker // productUnit is an rvalue reference to indicate this function consumes it, 115*0e209d39SAndroid Build Coastguard Worker // leaving it in a not-useful / undefined state. 116*0e209d39SAndroid Build Coastguard Worker static void processPatternTimes(MeasureUnitImpl &&productUnit, 117*0e209d39SAndroid Build Coastguard Worker Locale loc, 118*0e209d39SAndroid Build Coastguard Worker const UNumberUnitWidth &width, 119*0e209d39SAndroid Build Coastguard Worker const char *caseVariant, 120*0e209d39SAndroid Build Coastguard Worker UnicodeString *outArray, 121*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 122*0e209d39SAndroid Build Coastguard Worker 123*0e209d39SAndroid Build Coastguard Worker // Sets fModifiers to use the patterns from `simpleFormats`. 124*0e209d39SAndroid Build Coastguard Worker void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field, UErrorCode &status); 125*0e209d39SAndroid Build Coastguard Worker 126*0e209d39SAndroid Build Coastguard Worker // Sets fModifiers to a combination of `leadFormats` (one per plural form) 127*0e209d39SAndroid Build Coastguard Worker // and `trailFormat` appended to each. 128*0e209d39SAndroid Build Coastguard Worker // 129*0e209d39SAndroid Build Coastguard Worker // With a leadFormat of "{0}m" and a trailFormat of "{0}/s", it produces a 130*0e209d39SAndroid Build Coastguard Worker // pattern of "{0}m/s" by inserting each leadFormat pattern into trailFormat. 131*0e209d39SAndroid Build Coastguard Worker void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat, 132*0e209d39SAndroid Build Coastguard Worker Field field, UErrorCode &status); 133*0e209d39SAndroid Build Coastguard Worker }; 134*0e209d39SAndroid Build Coastguard Worker 135*0e209d39SAndroid Build Coastguard Worker // Similar to LongNameHandler, but only for MIXED units. 136*0e209d39SAndroid Build Coastguard Worker class MixedUnitLongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory { 137*0e209d39SAndroid Build Coastguard Worker public: 138*0e209d39SAndroid Build Coastguard Worker /** 139*0e209d39SAndroid Build Coastguard Worker * Construct a localized MixedUnitLongNameHandler for the specified 140*0e209d39SAndroid Build Coastguard Worker * MeasureUnit. It must be a MIXED unit. 141*0e209d39SAndroid Build Coastguard Worker * 142*0e209d39SAndroid Build Coastguard Worker * This function uses a fillIn instead of returning a pointer, because we 143*0e209d39SAndroid Build Coastguard Worker * want to fill in instances in a MemoryPool (which cannot adopt pointers it 144*0e209d39SAndroid Build Coastguard Worker * didn't create itself). 145*0e209d39SAndroid Build Coastguard Worker * 146*0e209d39SAndroid Build Coastguard Worker * @param loc The desired locale. 147*0e209d39SAndroid Build Coastguard Worker * @param mixedUnit The mixed measure unit to construct a 148*0e209d39SAndroid Build Coastguard Worker * MixedUnitLongNameHandler for. 149*0e209d39SAndroid Build Coastguard Worker * @param width Specifies the desired unit rendering. 150*0e209d39SAndroid Build Coastguard Worker * @param unitDisplayCase Specifies the desired grammatical case. If the 151*0e209d39SAndroid Build Coastguard Worker * specified case is not found, we fall back to nominative or no-case. 152*0e209d39SAndroid Build Coastguard Worker * @param rules Does not take ownership. 153*0e209d39SAndroid Build Coastguard Worker * @param parent Does not take ownership. 154*0e209d39SAndroid Build Coastguard Worker * @param fillIn Required. 155*0e209d39SAndroid Build Coastguard Worker */ 156*0e209d39SAndroid Build Coastguard Worker static void forMeasureUnit(const Locale &loc, 157*0e209d39SAndroid Build Coastguard Worker const MeasureUnit &mixedUnit, 158*0e209d39SAndroid Build Coastguard Worker const UNumberUnitWidth &width, 159*0e209d39SAndroid Build Coastguard Worker const char *unitDisplayCase, 160*0e209d39SAndroid Build Coastguard Worker const PluralRules *rules, 161*0e209d39SAndroid Build Coastguard Worker const MicroPropsGenerator *parent, 162*0e209d39SAndroid Build Coastguard Worker MixedUnitLongNameHandler *fillIn, 163*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 164*0e209d39SAndroid Build Coastguard Worker 165*0e209d39SAndroid Build Coastguard Worker /** 166*0e209d39SAndroid Build Coastguard Worker * Produces a plural-appropriate Modifier for a mixed unit: `quantity` is 167*0e209d39SAndroid Build Coastguard Worker * taken as the final smallest unit, while the larger unit values must be 168*0e209d39SAndroid Build Coastguard Worker * provided via `micros.mixedMeasures`. 169*0e209d39SAndroid Build Coastguard Worker */ 170*0e209d39SAndroid Build Coastguard Worker void processQuantity(DecimalQuantity &quantity, MicroProps µs, 171*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const override; 172*0e209d39SAndroid Build Coastguard Worker 173*0e209d39SAndroid Build Coastguard Worker // Required for ModifierStore. And ModifierStore is required by 174*0e209d39SAndroid Build Coastguard Worker // SimpleModifier constructor's last parameter. We assert his will never get 175*0e209d39SAndroid Build Coastguard Worker // called though. 176*0e209d39SAndroid Build Coastguard Worker const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const override; 177*0e209d39SAndroid Build Coastguard Worker 178*0e209d39SAndroid Build Coastguard Worker private: 179*0e209d39SAndroid Build Coastguard Worker // Not owned 180*0e209d39SAndroid Build Coastguard Worker const PluralRules *rules; 181*0e209d39SAndroid Build Coastguard Worker 182*0e209d39SAndroid Build Coastguard Worker // Not owned 183*0e209d39SAndroid Build Coastguard Worker const MicroPropsGenerator *parent; 184*0e209d39SAndroid Build Coastguard Worker 185*0e209d39SAndroid Build Coastguard Worker // Total number of units in the MeasureUnit this handler was configured for: 186*0e209d39SAndroid Build Coastguard Worker // for "foot-and-inch", this will be 2. 187*0e209d39SAndroid Build Coastguard Worker int32_t fMixedUnitCount = 1; 188*0e209d39SAndroid Build Coastguard Worker 189*0e209d39SAndroid Build Coastguard Worker // Stores unit data for each of the individual units. For each unit, it 190*0e209d39SAndroid Build Coastguard Worker // stores ARRAY_LENGTH strings, as returned by getMeasureData. (Each unit 191*0e209d39SAndroid Build Coastguard Worker // with index `i` has ARRAY_LENGTH strings starting at index 192*0e209d39SAndroid Build Coastguard Worker // `i*ARRAY_LENGTH` in this array.) 193*0e209d39SAndroid Build Coastguard Worker LocalArray<UnicodeString> fMixedUnitData; 194*0e209d39SAndroid Build Coastguard Worker 195*0e209d39SAndroid Build Coastguard Worker // Formats the larger units of Mixed Unit measurements. 196*0e209d39SAndroid Build Coastguard Worker LocalizedNumberFormatter fNumberFormatter; 197*0e209d39SAndroid Build Coastguard Worker 198*0e209d39SAndroid Build Coastguard Worker // Joins mixed units together. 199*0e209d39SAndroid Build Coastguard Worker LocalPointer<ListFormatter> fListFormatter; 200*0e209d39SAndroid Build Coastguard Worker MixedUnitLongNameHandler(const PluralRules * rules,const MicroPropsGenerator * parent)201*0e209d39SAndroid Build Coastguard Worker MixedUnitLongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent) 202*0e209d39SAndroid Build Coastguard Worker : rules(rules), parent(parent) { 203*0e209d39SAndroid Build Coastguard Worker } 204*0e209d39SAndroid Build Coastguard Worker MixedUnitLongNameHandler()205*0e209d39SAndroid Build Coastguard Worker MixedUnitLongNameHandler() : rules(nullptr), parent(nullptr) { 206*0e209d39SAndroid Build Coastguard Worker } 207*0e209d39SAndroid Build Coastguard Worker 208*0e209d39SAndroid Build Coastguard Worker // Allow macrosToMicroGenerator to call the private default constructor. 209*0e209d39SAndroid Build Coastguard Worker friend class NumberFormatterImpl; 210*0e209d39SAndroid Build Coastguard Worker 211*0e209d39SAndroid Build Coastguard Worker // Enables MemoryPool<LongNameHandler>::emplaceBack(): requires access to 212*0e209d39SAndroid Build Coastguard Worker // the private constructors. 213*0e209d39SAndroid Build Coastguard Worker friend class MemoryPool<MixedUnitLongNameHandler>; 214*0e209d39SAndroid Build Coastguard Worker 215*0e209d39SAndroid Build Coastguard Worker // For a mixed unit, returns a Modifier that takes only one parameter: the 216*0e209d39SAndroid Build Coastguard Worker // smallest and final unit of the set. The bigger units' values and labels 217*0e209d39SAndroid Build Coastguard Worker // get baked into this Modifier, together with the unit label of the final 218*0e209d39SAndroid Build Coastguard Worker // unit. 219*0e209d39SAndroid Build Coastguard Worker const Modifier *getMixedUnitModifier(DecimalQuantity &quantity, MicroProps µs, 220*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const; 221*0e209d39SAndroid Build Coastguard Worker }; 222*0e209d39SAndroid Build Coastguard Worker 223*0e209d39SAndroid Build Coastguard Worker /** 224*0e209d39SAndroid Build Coastguard Worker * A MicroPropsGenerator that multiplexes between different LongNameHandlers, 225*0e209d39SAndroid Build Coastguard Worker * depending on the outputUnit. 226*0e209d39SAndroid Build Coastguard Worker * 227*0e209d39SAndroid Build Coastguard Worker * See processQuantity() for the input requirements. 228*0e209d39SAndroid Build Coastguard Worker */ 229*0e209d39SAndroid Build Coastguard Worker class LongNameMultiplexer : public MicroPropsGenerator, public UMemory { 230*0e209d39SAndroid Build Coastguard Worker public: 231*0e209d39SAndroid Build Coastguard Worker // Produces a multiplexer for LongNameHandlers, one for each unit in 232*0e209d39SAndroid Build Coastguard Worker // `units`. An individual unit might be a mixed unit. 233*0e209d39SAndroid Build Coastguard Worker static LongNameMultiplexer *forMeasureUnits(const Locale &loc, 234*0e209d39SAndroid Build Coastguard Worker const MaybeStackVector<MeasureUnit> &units, 235*0e209d39SAndroid Build Coastguard Worker const UNumberUnitWidth &width, 236*0e209d39SAndroid Build Coastguard Worker const char *unitDisplayCase, 237*0e209d39SAndroid Build Coastguard Worker const PluralRules *rules, 238*0e209d39SAndroid Build Coastguard Worker const MicroPropsGenerator *parent, 239*0e209d39SAndroid Build Coastguard Worker UErrorCode &status); 240*0e209d39SAndroid Build Coastguard Worker 241*0e209d39SAndroid Build Coastguard Worker // The output unit must be provided via `micros.outputUnit`, it must match 242*0e209d39SAndroid Build Coastguard Worker // one of the units provided to the factory function. 243*0e209d39SAndroid Build Coastguard Worker void processQuantity(DecimalQuantity &quantity, MicroProps µs, 244*0e209d39SAndroid Build Coastguard Worker UErrorCode &status) const override; 245*0e209d39SAndroid Build Coastguard Worker 246*0e209d39SAndroid Build Coastguard Worker private: 247*0e209d39SAndroid Build Coastguard Worker /** 248*0e209d39SAndroid Build Coastguard Worker * Because we only know which LongNameHandler we wish to call after calling 249*0e209d39SAndroid Build Coastguard Worker * earlier MicroPropsGenerators in the chain, LongNameMultiplexer keeps the 250*0e209d39SAndroid Build Coastguard Worker * parent link, while the LongNameHandlers are given no parents. 251*0e209d39SAndroid Build Coastguard Worker */ 252*0e209d39SAndroid Build Coastguard Worker MemoryPool<LongNameHandler> fLongNameHandlers; 253*0e209d39SAndroid Build Coastguard Worker MemoryPool<MixedUnitLongNameHandler> fMixedUnitHandlers; 254*0e209d39SAndroid Build Coastguard Worker // Unowned pointers to instances owned by MaybeStackVectors. 255*0e209d39SAndroid Build Coastguard Worker MaybeStackArray<MicroPropsGenerator *, 8> fHandlers; 256*0e209d39SAndroid Build Coastguard Worker // Each MeasureUnit corresponds to the same-index MicroPropsGenerator 257*0e209d39SAndroid Build Coastguard Worker // pointed to in fHandlers. 258*0e209d39SAndroid Build Coastguard Worker LocalArray<MeasureUnit> fMeasureUnits; 259*0e209d39SAndroid Build Coastguard Worker 260*0e209d39SAndroid Build Coastguard Worker const MicroPropsGenerator *fParent; 261*0e209d39SAndroid Build Coastguard Worker LongNameMultiplexer(const MicroPropsGenerator * parent)262*0e209d39SAndroid Build Coastguard Worker LongNameMultiplexer(const MicroPropsGenerator *parent) : fParent(parent) { 263*0e209d39SAndroid Build Coastguard Worker } 264*0e209d39SAndroid Build Coastguard Worker }; 265*0e209d39SAndroid Build Coastguard Worker 266*0e209d39SAndroid Build Coastguard Worker } // namespace number::impl 267*0e209d39SAndroid Build Coastguard Worker U_NAMESPACE_END 268*0e209d39SAndroid Build Coastguard Worker 269*0e209d39SAndroid Build Coastguard Worker #endif //__NUMBER_LONGNAMES_H__ 270*0e209d39SAndroid Build Coastguard Worker 271*0e209d39SAndroid Build Coastguard Worker #endif /* #if !UCONFIG_NO_FORMATTING */ 272