273 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			273 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
| // © 2017 and later: Unicode, Inc. and others.
 | |
| // License & terms of use: http://www.unicode.org/copyright.html
 | |
| 
 | |
| #include "unicode/utypes.h"
 | |
| 
 | |
| #if !UCONFIG_NO_FORMATTING
 | |
| #ifndef __NUMBER_LONGNAMES_H__
 | |
| #define __NUMBER_LONGNAMES_H__
 | |
| 
 | |
| #include "cmemory.h"
 | |
| #include "unicode/listformatter.h"
 | |
| #include "unicode/uversion.h"
 | |
| #include "number_utils.h"
 | |
| #include "number_modifiers.h"
 | |
| 
 | |
| U_NAMESPACE_BEGIN namespace number {
 | |
| namespace impl {
 | |
| 
 | |
| // LongNameHandler takes care of formatting currency and measurement unit names,
 | |
| // as well as populating the gender of measure units.
 | |
| class LongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory {
 | |
|   public:
 | |
|     static UnicodeString getUnitDisplayName(
 | |
|         const Locale& loc,
 | |
|         const MeasureUnit& unit,
 | |
|         UNumberUnitWidth width,
 | |
|         UErrorCode& status);
 | |
| 
 | |
|     // This function does not support inflections or other newer NumberFormatter
 | |
|     // features: it exists to support the older not-recommended MeasureFormat.
 | |
|     static UnicodeString getUnitPattern(
 | |
|         const Locale& loc,
 | |
|         const MeasureUnit& unit,
 | |
|         UNumberUnitWidth width,
 | |
|         StandardPlural::Form pluralForm,
 | |
|         UErrorCode& status);
 | |
| 
 | |
|     static LongNameHandler*
 | |
|     forCurrencyLongNames(const Locale &loc, const CurrencyUnit ¤cy, const PluralRules *rules,
 | |
|                          const MicroPropsGenerator *parent, UErrorCode &status);
 | |
| 
 | |
|     /**
 | |
|      * Construct a localized LongNameHandler for the specified MeasureUnit.
 | |
|      *
 | |
|      * Mixed units are not supported, use MixedUnitLongNameHandler::forMeasureUnit.
 | |
|      *
 | |
|      * This function uses a fillIn instead of returning a pointer, because we
 | |
|      * want to fill in instances in a MemoryPool (which cannot adopt pointers it
 | |
|      * didn't create itself).
 | |
|      *
 | |
|      * @param loc The desired locale.
 | |
|      * @param unitRef The measure unit to construct a LongNameHandler for.
 | |
|      * @param width Specifies the desired unit rendering.
 | |
|      * @param unitDisplayCase Specifies the desired grammatical case. If the
 | |
|      *     specified case is not found, we fall back to nominative or no-case.
 | |
|      * @param rules Does not take ownership.
 | |
|      * @param parent Does not take ownership.
 | |
|      * @param fillIn Required.
 | |
|      */
 | |
|     static void forMeasureUnit(const Locale &loc,
 | |
|                                const MeasureUnit &unitRef,
 | |
|                                const UNumberUnitWidth &width,
 | |
|                                const char *unitDisplayCase,
 | |
|                                const PluralRules *rules,
 | |
|                                const MicroPropsGenerator *parent,
 | |
|                                LongNameHandler *fillIn,
 | |
|                                UErrorCode &status);
 | |
| 
 | |
|     /**
 | |
|      * Selects the plural-appropriate Modifier from the set of fModifiers based
 | |
|      * on the plural form.
 | |
|      */
 | |
|     void
 | |
|     processQuantity(DecimalQuantity &quantity, MicroProps µs, UErrorCode &status) const U_OVERRIDE;
 | |
| 
 | |
|     const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE;
 | |
| 
 | |
|   private:
 | |
|     // A set of pre-computed modifiers, one for each plural form.
 | |
|     SimpleModifier fModifiers[StandardPlural::Form::COUNT];
 | |
|     // Not owned
 | |
|     const PluralRules *rules;
 | |
|     // Not owned
 | |
|     const MicroPropsGenerator *parent;
 | |
|     // Grammatical gender of the formatted result. Not owned: must point at
 | |
|     // static or global strings.
 | |
|     const char *gender = "";
 | |
| 
 | |
|     LongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent)
 | |
|         : rules(rules), parent(parent) {
 | |
|     }
 | |
| 
 | |
|     LongNameHandler() : rules(nullptr), parent(nullptr) {
 | |
|     }
 | |
| 
 | |
|     // Enables MemoryPool<LongNameHandler>::emplaceBack(): requires access to
 | |
|     // the private constructors.
 | |
|     friend class MemoryPool<LongNameHandler>;
 | |
| 
 | |
|     // Allow macrosToMicroGenerator to call the private default constructor.
 | |
|     friend class NumberFormatterImpl;
 | |
| 
 | |
|     // Fills in LongNameHandler fields for formatting units identified `unit`.
 | |
|     static void forArbitraryUnit(const Locale &loc,
 | |
|                                  const MeasureUnit &unit,
 | |
|                                  const UNumberUnitWidth &width,
 | |
|                                  const char *unitDisplayCase,
 | |
|                                  LongNameHandler *fillIn,
 | |
|                                  UErrorCode &status);
 | |
| 
 | |
|     // Roughly corresponds to patternTimes(...) in the spec:
 | |
|     // https://unicode.org/reports/tr35/tr35-general.html#compound-units
 | |
|     //
 | |
|     // productUnit is an rvalue reference to indicate this function consumes it,
 | |
|     // leaving it in a not-useful / undefined state.
 | |
|     static void processPatternTimes(MeasureUnitImpl &&productUnit,
 | |
|                                     Locale loc,
 | |
|                                     const UNumberUnitWidth &width,
 | |
|                                     const char *caseVariant,
 | |
|                                     UnicodeString *outArray,
 | |
|                                     UErrorCode &status);
 | |
| 
 | |
|     // Sets fModifiers to use the patterns from `simpleFormats`.
 | |
|     void simpleFormatsToModifiers(const UnicodeString *simpleFormats, Field field, UErrorCode &status);
 | |
| 
 | |
|     // Sets fModifiers to a combination of `leadFormats` (one per plural form)
 | |
|     // and `trailFormat` appended to each.
 | |
|     //
 | |
|     // With a leadFormat of "{0}m" and a trailFormat of "{0}/s", it produces a
 | |
|     // pattern of "{0}m/s" by inserting each leadFormat pattern into trailFormat.
 | |
|     void multiSimpleFormatsToModifiers(const UnicodeString *leadFormats, UnicodeString trailFormat,
 | |
|                                        Field field, UErrorCode &status);
 | |
| };
 | |
| 
 | |
| // Similar to LongNameHandler, but only for MIXED units.
 | |
| class MixedUnitLongNameHandler : public MicroPropsGenerator, public ModifierStore, public UMemory {
 | |
|   public:
 | |
|     /**
 | |
|      * Construct a localized MixedUnitLongNameHandler for the specified
 | |
|      * MeasureUnit. It must be a MIXED unit.
 | |
|      *
 | |
|      * This function uses a fillIn instead of returning a pointer, because we
 | |
|      * want to fill in instances in a MemoryPool (which cannot adopt pointers it
 | |
|      * didn't create itself).
 | |
|      *
 | |
|      * @param loc The desired locale.
 | |
|      * @param mixedUnit The mixed measure unit to construct a
 | |
|      *     MixedUnitLongNameHandler for.
 | |
|      * @param width Specifies the desired unit rendering.
 | |
|      * @param unitDisplayCase Specifies the desired grammatical case. If the
 | |
|      *     specified case is not found, we fall back to nominative or no-case.
 | |
|      * @param rules Does not take ownership.
 | |
|      * @param parent Does not take ownership.
 | |
|      * @param fillIn Required.
 | |
|      */
 | |
|     static void forMeasureUnit(const Locale &loc,
 | |
|                                const MeasureUnit &mixedUnit,
 | |
|                                const UNumberUnitWidth &width,
 | |
|                                const char *unitDisplayCase,
 | |
|                                const PluralRules *rules,
 | |
|                                const MicroPropsGenerator *parent,
 | |
|                                MixedUnitLongNameHandler *fillIn,
 | |
|                                UErrorCode &status);
 | |
| 
 | |
|     /**
 | |
|      * Produces a plural-appropriate Modifier for a mixed unit: `quantity` is
 | |
|      * taken as the final smallest unit, while the larger unit values must be
 | |
|      * provided via `micros.mixedMeasures`.
 | |
|      */
 | |
|     void processQuantity(DecimalQuantity &quantity, MicroProps µs,
 | |
|                          UErrorCode &status) const U_OVERRIDE;
 | |
| 
 | |
|     // Required for ModifierStore. And ModifierStore is required by
 | |
|     // SimpleModifier constructor's last parameter. We assert his will never get
 | |
|     // called though.
 | |
|     const Modifier *getModifier(Signum signum, StandardPlural::Form plural) const U_OVERRIDE;
 | |
| 
 | |
|   private:
 | |
|     // Not owned
 | |
|     const PluralRules *rules;
 | |
| 
 | |
|     // Not owned
 | |
|     const MicroPropsGenerator *parent;
 | |
| 
 | |
|     // Total number of units in the MeasureUnit this handler was configured for:
 | |
|     // for "foot-and-inch", this will be 2.
 | |
|     int32_t fMixedUnitCount = 1;
 | |
| 
 | |
|     // Stores unit data for each of the individual units. For each unit, it
 | |
|     // stores ARRAY_LENGTH strings, as returned by getMeasureData. (Each unit
 | |
|     // with index `i` has ARRAY_LENGTH strings starting at index
 | |
|     // `i*ARRAY_LENGTH` in this array.)
 | |
|     LocalArray<UnicodeString> fMixedUnitData;
 | |
| 
 | |
|     // Formats the larger units of Mixed Unit measurements.
 | |
|     LocalizedNumberFormatter fNumberFormatter;
 | |
| 
 | |
|     // Joins mixed units together.
 | |
|     LocalPointer<ListFormatter> fListFormatter;
 | |
| 
 | |
|     MixedUnitLongNameHandler(const PluralRules *rules, const MicroPropsGenerator *parent)
 | |
|         : rules(rules), parent(parent) {
 | |
|     }
 | |
| 
 | |
|     MixedUnitLongNameHandler() : rules(nullptr), parent(nullptr) {
 | |
|     }
 | |
| 
 | |
|     // Allow macrosToMicroGenerator to call the private default constructor.
 | |
|     friend class NumberFormatterImpl;
 | |
| 
 | |
|     // Enables MemoryPool<LongNameHandler>::emplaceBack(): requires access to
 | |
|     // the private constructors.
 | |
|     friend class MemoryPool<MixedUnitLongNameHandler>;
 | |
| 
 | |
|     // For a mixed unit, returns a Modifier that takes only one parameter: the
 | |
|     // smallest and final unit of the set. The bigger units' values and labels
 | |
|     // get baked into this Modifier, together with the unit label of the final
 | |
|     // unit.
 | |
|     const Modifier *getMixedUnitModifier(DecimalQuantity &quantity, MicroProps µs,
 | |
|                                          UErrorCode &status) const;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * A MicroPropsGenerator that multiplexes between different LongNameHandlers,
 | |
|  * depending on the outputUnit.
 | |
|  *
 | |
|  * See processQuantity() for the input requirements.
 | |
|  */
 | |
| class LongNameMultiplexer : public MicroPropsGenerator, public UMemory {
 | |
|   public:
 | |
|     // Produces a multiplexer for LongNameHandlers, one for each unit in
 | |
|     // `units`. An individual unit might be a mixed unit.
 | |
|     static LongNameMultiplexer *forMeasureUnits(const Locale &loc,
 | |
|                                                 const MaybeStackVector<MeasureUnit> &units,
 | |
|                                                 const UNumberUnitWidth &width,
 | |
|                                                 const char *unitDisplayCase,
 | |
|                                                 const PluralRules *rules,
 | |
|                                                 const MicroPropsGenerator *parent,
 | |
|                                                 UErrorCode &status);
 | |
| 
 | |
|     // The output unit must be provided via `micros.outputUnit`, it must match
 | |
|     // one of the units provided to the factory function.
 | |
|     void processQuantity(DecimalQuantity &quantity, MicroProps µs,
 | |
|                          UErrorCode &status) const U_OVERRIDE;
 | |
| 
 | |
|   private:
 | |
|     /**
 | |
|      * Because we only know which LongNameHandler we wish to call after calling
 | |
|      * earlier MicroPropsGenerators in the chain, LongNameMultiplexer keeps the
 | |
|      * parent link, while the LongNameHandlers are given no parents.
 | |
|      */
 | |
|     MemoryPool<LongNameHandler> fLongNameHandlers;
 | |
|     MemoryPool<MixedUnitLongNameHandler> fMixedUnitHandlers;
 | |
|     // Unowned pointers to instances owned by MaybeStackVectors.
 | |
|     MaybeStackArray<MicroPropsGenerator *, 8> fHandlers;
 | |
|     // Each MeasureUnit corresponds to the same-index MicroPropsGenerator
 | |
|     // pointed to in fHandlers.
 | |
|     LocalArray<MeasureUnit> fMeasureUnits;
 | |
| 
 | |
|     const MicroPropsGenerator *fParent;
 | |
| 
 | |
|     LongNameMultiplexer(const MicroPropsGenerator *parent) : fParent(parent) {
 | |
|     }
 | |
| };
 | |
| 
 | |
| }  // namespace impl
 | |
| }  // namespace number
 | |
| U_NAMESPACE_END
 | |
| 
 | |
| #endif //__NUMBER_LONGNAMES_H__
 | |
| 
 | |
| #endif /* #if !UCONFIG_NO_FORMATTING */
 |