From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- intl/icu/source/i18n/number_longnames.h | 272 ++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 intl/icu/source/i18n/number_longnames.h (limited to 'intl/icu/source/i18n/number_longnames.h') diff --git a/intl/icu/source/i18n/number_longnames.h b/intl/icu/source/i18n/number_longnames.h new file mode 100644 index 0000000000..56d8c9b24e --- /dev/null +++ b/intl/icu/source/i18n/number_longnames.h @@ -0,0 +1,272 @@ +// © 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 override; + + const Modifier* getModifier(Signum signum, StandardPlural::Form plural) const 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::emplaceBack(): requires access to + // the private constructors. + friend class MemoryPool; + + // 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 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 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 fMixedUnitData; + + // Formats the larger units of Mixed Unit measurements. + LocalizedNumberFormatter fNumberFormatter; + + // Joins mixed units together. + LocalPointer 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::emplaceBack(): requires access to + // the private constructors. + friend class MemoryPool; + + // 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 &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 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 fLongNameHandlers; + MemoryPool fMixedUnitHandlers; + // Unowned pointers to instances owned by MaybeStackVectors. + MaybeStackArray fHandlers; + // Each MeasureUnit corresponds to the same-index MicroPropsGenerator + // pointed to in fHandlers. + LocalArray 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 */ -- cgit v1.2.3