tor-browser

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

messageformat2_function_registry_internal.h (15111B)


      1 // © 2024 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 #ifndef U_HIDE_DEPRECATED_API
      7 
      8 #ifndef MESSAGEFORMAT2_FUNCTION_REGISTRY_INTERNAL_H
      9 #define MESSAGEFORMAT2_FUNCTION_REGISTRY_INTERNAL_H
     10 
     11 #if U_SHOW_CPLUSPLUS_API
     12 
     13 #if !UCONFIG_NO_NORMALIZATION
     14 
     15 #if !UCONFIG_NO_FORMATTING
     16 
     17 #if !UCONFIG_NO_MF2
     18 
     19 #include "unicode/datefmt.h"
     20 #include "unicode/messageformat2_function_registry.h"
     21 
     22 U_NAMESPACE_BEGIN
     23 
     24 namespace message2 {
     25 
     26 // Constants for option names
     27 namespace options {
     28 static constexpr std::u16string_view ALWAYS = u"always";
     29 static constexpr std::u16string_view COMPACT = u"compact";
     30 static constexpr std::u16string_view COMPACT_DISPLAY = u"compactDisplay";
     31 static constexpr std::u16string_view DATE_STYLE = u"dateStyle";
     32 static constexpr std::u16string_view DAY = u"day";
     33 static constexpr std::u16string_view DECIMAL_PLACES = u"decimalPlaces";
     34 static constexpr std::u16string_view DEFAULT_UPPER = u"DEFAULT";
     35 static constexpr std::u16string_view ENGINEERING = u"engineering";
     36 static constexpr std::u16string_view EXACT = u"exact";
     37 static constexpr std::u16string_view EXCEPT_ZERO = u"exceptZero";
     38 static constexpr std::u16string_view FAILS = u"fails";
     39 static constexpr std::u16string_view FULL_UPPER = u"FULL";
     40 static constexpr std::u16string_view HOUR = u"hour";
     41 static constexpr std::u16string_view LONG = u"long";
     42 static constexpr std::u16string_view LONG_UPPER = u"LONG";
     43 static constexpr std::u16string_view MAXIMUM_FRACTION_DIGITS = u"maximumFractionDigits";
     44 static constexpr std::u16string_view MAXIMUM_SIGNIFICANT_DIGITS = u"maximumSignificantDigits";
     45 static constexpr std::u16string_view MEDIUM_UPPER = u"MEDIUM";
     46 static constexpr std::u16string_view MIN2 = u"min2";
     47 static constexpr std::u16string_view MINIMUM_FRACTION_DIGITS = u"minimumFractionDigits";
     48 static constexpr std::u16string_view MINIMUM_INTEGER_DIGITS = u"minimumIntegerDigits";
     49 static constexpr std::u16string_view MINIMUM_SIGNIFICANT_DIGITS = u"minimumSignificantDigits";
     50 static constexpr std::u16string_view MINUTE = u"minute";
     51 static constexpr std::u16string_view MONTH = u"month";
     52 static constexpr std::u16string_view NARROW = u"narrow";
     53 static constexpr std::u16string_view NEGATIVE = u"negative";
     54 static constexpr std::u16string_view NEVER = u"never";
     55 static constexpr std::u16string_view NOTATION = u"notation";
     56 static constexpr std::u16string_view NUMBERING_SYSTEM = u"numberingSystem";
     57 static constexpr std::u16string_view NUMERIC = u"numeric";
     58 static constexpr std::u16string_view ORDINAL = u"ordinal";
     59 static constexpr std::u16string_view PERCENT_STRING = u"percent";
     60 static constexpr std::u16string_view SCIENTIFIC = u"scientific";
     61 static constexpr std::u16string_view SECOND = u"second";
     62 static constexpr std::u16string_view SELECT = u"select";
     63 static constexpr std::u16string_view SHORT = u"short";
     64 static constexpr std::u16string_view SHORT_UPPER = u"SHORT";
     65 static constexpr std::u16string_view SIGN_DISPLAY = u"signDisplay";
     66 static constexpr std::u16string_view STYLE = u"style";
     67 static constexpr std::u16string_view TIME_STYLE = u"timeStyle";
     68 static constexpr std::u16string_view TWO_DIGIT = u"2-digit";
     69 static constexpr std::u16string_view USE_GROUPING = u"useGrouping";
     70 static constexpr std::u16string_view WEEKDAY = u"weekday";
     71 static constexpr std::u16string_view YEAR = u"year";
     72 } // namespace options
     73 
     74    // Built-in functions
     75    /*
     76      The standard functions are :datetime, :date, :time,
     77      :number, :integer, and :string,
     78      per https://github.com/unicode-org/message-format-wg/blob/main/spec/registry.md
     79      as of https://github.com/unicode-org/message-format-wg/releases/tag/LDML45-alpha
     80    */
     81    class StandardFunctions {
     82        friend class MessageFormatter;
     83 
     84        public:
     85        // Used for normalizing variable names and keys for comparison
     86        static UnicodeString normalizeNFC(const UnicodeString&);
     87 
     88        private:
     89        static void validateDigitSizeOptions(const FunctionOptions&, UErrorCode&);
     90        static void checkSelectOption(const FunctionOptions&, UErrorCode&);
     91        static UnicodeString getStringOption(const FunctionOptions& opts,
     92                                             std::u16string_view optionName,
     93                                             UErrorCode& errorCode);
     94 
     95        class DateTime;
     96 
     97        class DateTimeFactory : public FormatterFactory {
     98        public:
     99            Formatter* createFormatter(const Locale& locale, UErrorCode& status) override;
    100            static DateTimeFactory* date(UErrorCode&);
    101            static DateTimeFactory* time(UErrorCode&);
    102            static DateTimeFactory* dateTime(UErrorCode&);
    103            DateTimeFactory() = delete;
    104            virtual ~DateTimeFactory();
    105 
    106        private:
    107            friend class DateTime;
    108 
    109            typedef enum DateTimeType {
    110                Date,
    111                Time,
    112                DateTime
    113            } DateTimeType;
    114 
    115            DateTimeType type;
    116            DateTimeFactory(DateTimeType t) : type(t) {}
    117        };
    118 
    119        class DateTime : public Formatter {
    120        public:
    121            FormattedPlaceholder format(FormattedPlaceholder&& toFormat, FunctionOptions&& options, UErrorCode& status) const override;
    122            virtual ~DateTime();
    123 
    124        private:
    125            const Locale& locale;
    126            const DateTimeFactory::DateTimeType type;
    127            friend class DateTimeFactory;
    128            DateTime(const Locale& l, DateTimeFactory::DateTimeType t)
    129                : locale(l), type(t) {}
    130            const LocalPointer<icu::DateFormat> icuFormatter;
    131 
    132            // Methods for parsing date literals
    133            UDate tryPatterns(const UnicodeString&, UErrorCode&) const;
    134            UDate tryTimeZonePatterns(const UnicodeString&, UErrorCode&) const;
    135            DateInfo createDateInfoFromString(const UnicodeString&, UErrorCode&) const;
    136 
    137            /*
    138              Looks up an option by name, first checking `opts`, then the cached options
    139              in `toFormat` if applicable, and finally using a default
    140 
    141              Ignores any options with non-string values
    142             */
    143            UnicodeString getFunctionOption(const FormattedPlaceholder& toFormat,
    144                                            const FunctionOptions& opts,
    145                                            std::u16string_view optionName) const;
    146            // Version for options that don't have defaults; sets the error
    147            // code instead of returning a default value
    148            UnicodeString getFunctionOption(const FormattedPlaceholder& toFormat,
    149                                            const FunctionOptions& opts,
    150                                            std::u16string_view optionName,
    151                                            UErrorCode& errorCode) const;
    152 
    153        };
    154 
    155        // Note: IntegerFactory doesn't implement SelectorFactory;
    156        // instead, an instance of PluralFactory is registered to the integer
    157        // selector
    158        // TODO
    159        class IntegerFactory : public FormatterFactory {
    160        public:
    161            Formatter* createFormatter(const Locale& locale, UErrorCode& status) override;
    162            virtual ~IntegerFactory();
    163        };
    164 
    165        class NumberFactory : public FormatterFactory {
    166        public:
    167            Formatter* createFormatter(const Locale& locale, UErrorCode& status) override;
    168            virtual ~NumberFactory();
    169        private:
    170            friend class IntegerFactory;
    171            static NumberFactory integer(const Locale& locale, UErrorCode& status);
    172        };
    173 
    174        class Number : public Formatter {
    175        public:
    176            FormattedPlaceholder format(FormattedPlaceholder&& toFormat, FunctionOptions&& options, UErrorCode& status) const override;
    177            virtual ~Number();
    178 
    179        private:
    180            friend class NumberFactory;
    181            friend class StandardFunctions;
    182 
    183            Number(const Locale& loc) : locale(loc), icuFormatter(number::NumberFormatter::withLocale(loc)) {}
    184            Number(const Locale& loc, bool isInt) : locale(loc), isInteger(isInt), icuFormatter(number::NumberFormatter::withLocale(loc)) {}
    185            static Number integer(const Locale& loc);
    186 
    187        // These options have their own accessor methods, since they have different default values.
    188            int32_t maximumFractionDigits(const FunctionOptions& options) const;
    189            int32_t minimumFractionDigits(const FunctionOptions& options) const;
    190            int32_t minimumSignificantDigits(const FunctionOptions& options) const;
    191            int32_t maximumSignificantDigits(const FunctionOptions& options) const;
    192            int32_t minimumIntegerDigits(const FunctionOptions& options) const;
    193 
    194            bool usePercent(const FunctionOptions& options) const;
    195            const Locale& locale;
    196            const bool isInteger = false;
    197            const number::LocalizedNumberFormatter icuFormatter;
    198        };
    199 
    200        static number::LocalizedNumberFormatter formatterForOptions(const Number& number,
    201                                                                    const FunctionOptions& opts,
    202                                                                    UErrorCode& status);
    203 
    204        class PluralFactory : public SelectorFactory {
    205        public:
    206            Selector* createSelector(const Locale& locale, UErrorCode& status) const override;
    207            virtual ~PluralFactory();
    208 
    209        private:
    210            friend class IntegerFactory;
    211            friend class MessageFormatter;
    212 
    213            PluralFactory() {}
    214            PluralFactory(bool isInt) : isInteger(isInt) {}
    215            static PluralFactory integer() { return PluralFactory(true);}
    216            const bool isInteger = false;
    217        };
    218 
    219        class Plural : public Selector {
    220        public:
    221            void selectKey(FormattedPlaceholder&& val,
    222                           FunctionOptions&& options,
    223                           const UnicodeString* keys,
    224                           int32_t keysLen,
    225                           UnicodeString* prefs,
    226                           int32_t& prefsLen,
    227                           UErrorCode& status) const override;
    228            virtual ~Plural();
    229 
    230        private:
    231            friend class IntegerFactory;
    232            friend class PluralFactory;
    233 
    234            // Can't use UPluralType for this since we want to include
    235            // exact matching as an option
    236            typedef enum PluralType {
    237                PLURAL_ORDINAL,
    238                PLURAL_CARDINAL,
    239                PLURAL_EXACT
    240            } PluralType;
    241            Plural(const Locale& loc, UErrorCode& errorCode);
    242            Plural(const Locale& loc, bool isInt, UErrorCode& errorCode);
    243            static Plural integer(const Locale& loc, UErrorCode& errorCode) { return Plural(loc, true, errorCode); }
    244            PluralType pluralType(const FunctionOptions& opts) const;
    245            const Locale& locale;
    246            const bool isInteger = false;
    247            LocalPointer<StandardFunctions::Number> numberFormatter;
    248        };
    249 
    250        class TextFactory : public SelectorFactory {
    251        public:
    252            Selector* createSelector(const Locale& locale, UErrorCode& status) const override;
    253            virtual ~TextFactory();
    254        };
    255 
    256        class TextSelector : public Selector {
    257        public:
    258            void selectKey(FormattedPlaceholder&& val,
    259                           FunctionOptions&& options,
    260                           const UnicodeString* keys,
    261                           int32_t keysLen,
    262                           UnicodeString* prefs,
    263                           int32_t& prefsLen,
    264                           UErrorCode& status) const override;
    265            virtual ~TextSelector();
    266 
    267        private:
    268            friend class TextFactory;
    269 
    270            // Formatting `value` to a string might require the locale
    271            const Locale& locale;
    272 
    273            TextSelector(const Locale& l) : locale(l) {}
    274        };
    275 
    276        // See https://github.com/unicode-org/message-format-wg/blob/main/test/README.md
    277        class TestFormatFactory : public FormatterFactory {
    278        public:
    279            Formatter* createFormatter(const Locale& locale, UErrorCode& status) override;
    280            TestFormatFactory() {}
    281            virtual ~TestFormatFactory();
    282        };
    283 
    284        class TestSelect;
    285 
    286        class TestFormat : public Formatter {
    287        public:
    288            FormattedPlaceholder format(FormattedPlaceholder&& toFormat, FunctionOptions&& options, UErrorCode& status) const override;
    289            virtual ~TestFormat();
    290 
    291        private:
    292            friend class TestFormatFactory;
    293            friend class TestSelect;
    294            TestFormat() {}
    295            static void testFunctionParameters(const FormattedPlaceholder& arg,
    296                                               const FunctionOptions& options,
    297                                               int32_t& decimalPlaces,
    298                                               bool& failsFormat,
    299                                               bool& failsSelect,
    300                                               double& input,
    301                                               UErrorCode& status);
    302 
    303        };
    304 
    305        // See https://github.com/unicode-org/message-format-wg/blob/main/test/README.md
    306        class TestSelectFactory : public SelectorFactory {
    307        public:
    308            Selector* createSelector(const Locale& locale, UErrorCode& status) const override;
    309            TestSelectFactory() {}
    310            virtual ~TestSelectFactory();
    311        };
    312 
    313        class TestSelect : public Selector {
    314        public:
    315            void selectKey(FormattedPlaceholder&& val,
    316                           FunctionOptions&& options,
    317                           const UnicodeString* keys,
    318                           int32_t keysLen,
    319                           UnicodeString* prefs,
    320                           int32_t& prefsLen,
    321                           UErrorCode& status) const override;
    322            virtual ~TestSelect();
    323 
    324        private:
    325            friend class TestSelectFactory;
    326            TestSelect() {}
    327        };
    328 
    329    };
    330 
    331    extern void formatDateWithDefaults(const Locale& locale, const DateInfo& date, UnicodeString&, UErrorCode& errorCode);
    332    extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, double toFormat, UErrorCode& errorCode);
    333    extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, int32_t toFormat, UErrorCode& errorCode);
    334    extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, int64_t toFormat, UErrorCode& errorCode);
    335    extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, StringPiece toFormat, UErrorCode& errorCode);
    336    extern DateFormat* defaultDateTimeInstance(const Locale&, UErrorCode&);
    337 
    338 } // namespace message2
    339 
    340 U_NAMESPACE_END
    341 
    342 #endif /* #if !UCONFIG_NO_MF2 */
    343 
    344 #endif /* #if !UCONFIG_NO_FORMATTING */
    345 
    346 #endif /* #if !UCONFIG_NO_NORMALIZATION */
    347 
    348 #endif /* U_SHOW_CPLUSPLUS_API */
    349 
    350 #endif // MESSAGEFORMAT2_FUNCTION_REGISTRY_INTERNAL_H
    351 
    352 #endif // U_HIDE_DEPRECATED_API
    353 // eof