tor-browser

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

number_longnames.h (11408B)


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