• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_FORMATTING
14 
15 #if !UCONFIG_NO_MF2
16 
17 #include "unicode/datefmt.h"
18 #include "unicode/messageformat2_function_registry.h"
19 
20 U_NAMESPACE_BEGIN
21 
22 namespace message2 {
23 
24     // Built-in functions
25     /*
26       The standard functions are :datetime, :date, :time,
27       :number, :integer, and :string,
28       per https://github.com/unicode-org/message-format-wg/blob/main/spec/registry.md
29       as of https://github.com/unicode-org/message-format-wg/releases/tag/LDML45-alpha
30     */
31     class StandardFunctions {
32         friend class MessageFormatter;
33 
34         static UnicodeString getStringOption(const FunctionOptions& opts,
35                                              const UnicodeString& optionName,
36                                              UErrorCode& errorCode);
37 
38         class DateTime;
39 
40         class DateTimeFactory : public FormatterFactory {
41         public:
42             Formatter* createFormatter(const Locale& locale, UErrorCode& status) override;
43             static DateTimeFactory* date(UErrorCode&);
44             static DateTimeFactory* time(UErrorCode&);
45             static DateTimeFactory* dateTime(UErrorCode&);
46             DateTimeFactory() = delete;
47             virtual ~DateTimeFactory();
48 
49         private:
50             friend class DateTime;
51 
52             typedef enum DateTimeType {
53                 Date,
54                 Time,
55                 DateTime
56             } DateTimeType;
57 
58             DateTimeType type;
DateTimeFactory(DateTimeType t)59             DateTimeFactory(DateTimeType t) : type(t) {}
60         };
61 
62         class DateTime : public Formatter {
63         public:
64             FormattedPlaceholder format(FormattedPlaceholder&& toFormat, FunctionOptions&& options, UErrorCode& status) const override;
65             virtual ~DateTime();
66 
67         private:
68             const Locale& locale;
69             const DateTimeFactory::DateTimeType type;
70             friend class DateTimeFactory;
DateTime(const Locale & l,DateTimeFactory::DateTimeType t)71             DateTime(const Locale& l, DateTimeFactory::DateTimeType t) : locale(l), type(t) {}
72             const LocalPointer<icu::DateFormat> icuFormatter;
73 
74             /*
75               Looks up an option by name, first checking `opts`, then the cached options
76               in `toFormat` if applicable, and finally using a default
77 
78               Ignores any options with non-string values
79              */
80             UnicodeString getFunctionOption(const FormattedPlaceholder& toFormat,
81                                             const FunctionOptions& opts,
82                                             const UnicodeString& optionName) const;
83             // Version for options that don't have defaults; sets the error
84             // code instead of returning a default value
85             UnicodeString getFunctionOption(const FormattedPlaceholder& toFormat,
86                                             const FunctionOptions& opts,
87                                             const UnicodeString& optionName,
88                                             UErrorCode& errorCode) const;
89 
90         };
91 
92         // Note: IntegerFactory doesn't implement SelectorFactory;
93         // instead, an instance of PluralFactory is registered to the integer
94         // selector
95         // TODO
96         class IntegerFactory : public FormatterFactory {
97         public:
98             Formatter* createFormatter(const Locale& locale, UErrorCode& status) override;
99             virtual ~IntegerFactory();
100         };
101 
102         class NumberFactory : public FormatterFactory {
103         public:
104             Formatter* createFormatter(const Locale& locale, UErrorCode& status) override;
105             virtual ~NumberFactory();
106         private:
107             friend class IntegerFactory;
108             static NumberFactory integer(const Locale& locale, UErrorCode& status);
109         };
110 
111         class Number : public Formatter {
112         public:
113             FormattedPlaceholder format(FormattedPlaceholder&& toFormat, FunctionOptions&& options, UErrorCode& status) const override;
114             virtual ~Number();
115 
116         private:
117             friend class NumberFactory;
118             friend class StandardFunctions;
119 
Number(const Locale & loc)120             Number(const Locale& loc) : locale(loc), icuFormatter(number::NumberFormatter::withLocale(loc)) {}
Number(const Locale & loc,bool isInt)121             Number(const Locale& loc, bool isInt) : locale(loc), isInteger(isInt), icuFormatter(number::NumberFormatter::withLocale(loc)) {}
122             static Number integer(const Locale& loc);
123 
124         // These options have their own accessor methods, since they have different default values.
125             int32_t maximumFractionDigits(const FunctionOptions& options) const;
126             int32_t minimumFractionDigits(const FunctionOptions& options) const;
127             int32_t minimumSignificantDigits(const FunctionOptions& options) const;
128             int32_t maximumSignificantDigits(const FunctionOptions& options) const;
129             int32_t minimumIntegerDigits(const FunctionOptions& options) const;
130 
131             bool usePercent(const FunctionOptions& options) const;
132             const Locale& locale;
133             const bool isInteger = false;
134             const number::LocalizedNumberFormatter icuFormatter;
135         };
136 
137         static number::LocalizedNumberFormatter formatterForOptions(const Number& number,
138                                                                     const FunctionOptions& opts,
139                                                                     UErrorCode& status);
140 
141         class PluralFactory : public SelectorFactory {
142         public:
143             Selector* createSelector(const Locale& locale, UErrorCode& status) const override;
144             virtual ~PluralFactory();
145 
146         private:
147             friend class IntegerFactory;
148             friend class MessageFormatter;
149 
PluralFactory()150             PluralFactory() {}
PluralFactory(bool isInt)151             PluralFactory(bool isInt) : isInteger(isInt) {}
integer()152             static PluralFactory integer() { return PluralFactory(true);}
153             const bool isInteger = false;
154         };
155 
156         class Plural : public Selector {
157         public:
158             void selectKey(FormattedPlaceholder&& val,
159                            FunctionOptions&& options,
160                            const UnicodeString* keys,
161                            int32_t keysLen,
162                            UnicodeString* prefs,
163                            int32_t& prefsLen,
164                            UErrorCode& status) const override;
165             virtual ~Plural();
166 
167         private:
168             friend class IntegerFactory;
169             friend class PluralFactory;
170 
171             // Can't use UPluralType for this since we want to include
172             // exact matching as an option
173             typedef enum PluralType {
174                 PLURAL_ORDINAL,
175                 PLURAL_CARDINAL,
176                 PLURAL_EXACT
177             } PluralType;
Plural(const Locale & loc)178             Plural(const Locale& loc) : locale(loc) {}
Plural(const Locale & loc,bool isInt)179             Plural(const Locale& loc, bool isInt) : locale(loc), isInteger(isInt) {}
integer(const Locale & loc)180             static Plural integer(const Locale& loc) { return Plural(loc, true); }
181             PluralType pluralType(const FunctionOptions& opts) const;
182             const Locale& locale;
183             const bool isInteger = false;
184         };
185 
186         class TextFactory : public SelectorFactory {
187         public:
188             Selector* createSelector(const Locale& locale, UErrorCode& status) const override;
189             virtual ~TextFactory();
190         };
191 
192         class TextSelector : public Selector {
193         public:
194             void selectKey(FormattedPlaceholder&& val,
195                            FunctionOptions&& options,
196                            const UnicodeString* keys,
197                            int32_t keysLen,
198                            UnicodeString* prefs,
199                            int32_t& prefsLen,
200                            UErrorCode& status) const override;
201             virtual ~TextSelector();
202 
203         private:
204             friend class TextFactory;
205 
206             // Formatting `value` to a string might require the locale
207             const Locale& locale;
208 
TextSelector(const Locale & l)209             TextSelector(const Locale& l) : locale(l) {}
210         };
211     };
212 
213     extern void formatDateWithDefaults(const Locale& locale, UDate date, UnicodeString&, UErrorCode& errorCode);
214     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, double toFormat, UErrorCode& errorCode);
215     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, int32_t toFormat, UErrorCode& errorCode);
216     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, int64_t toFormat, UErrorCode& errorCode);
217     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, StringPiece toFormat, UErrorCode& errorCode);
218     extern DateFormat* defaultDateTimeInstance(const Locale&, UErrorCode&);
219 
220 } // namespace message2
221 
222 U_NAMESPACE_END
223 
224 #endif /* #if !UCONFIG_NO_MF2 */
225 
226 #endif /* #if !UCONFIG_NO_FORMATTING */
227 
228 #endif /* U_SHOW_CPLUSPLUS_API */
229 
230 #endif // MESSAGEFORMAT2_FUNCTION_REGISTRY_INTERNAL_H
231 
232 #endif // U_HIDE_DEPRECATED_API
233 // eof
234