• 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;
178             Plural(const Locale& loc, UErrorCode& errorCode);
179             Plural(const Locale& loc, bool isInt, UErrorCode& errorCode);
integer(const Locale & loc,UErrorCode & errorCode)180             static Plural integer(const Locale& loc, UErrorCode& errorCode) { return Plural(loc, true, errorCode); }
181             PluralType pluralType(const FunctionOptions& opts) const;
182             const Locale& locale;
183             const bool isInteger = false;
184             LocalPointer<StandardFunctions::Number> numberFormatter;
185         };
186 
187         class TextFactory : public SelectorFactory {
188         public:
189             Selector* createSelector(const Locale& locale, UErrorCode& status) const override;
190             virtual ~TextFactory();
191         };
192 
193         class TextSelector : public Selector {
194         public:
195             void selectKey(FormattedPlaceholder&& val,
196                            FunctionOptions&& options,
197                            const UnicodeString* keys,
198                            int32_t keysLen,
199                            UnicodeString* prefs,
200                            int32_t& prefsLen,
201                            UErrorCode& status) const override;
202             virtual ~TextSelector();
203 
204         private:
205             friend class TextFactory;
206 
207             // Formatting `value` to a string might require the locale
208             const Locale& locale;
209 
TextSelector(const Locale & l)210             TextSelector(const Locale& l) : locale(l) {}
211         };
212     };
213 
214     extern void formatDateWithDefaults(const Locale& locale, UDate date, UnicodeString&, UErrorCode& errorCode);
215     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, double toFormat, UErrorCode& errorCode);
216     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, int32_t toFormat, UErrorCode& errorCode);
217     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, int64_t toFormat, UErrorCode& errorCode);
218     extern number::FormattedNumber formatNumberWithDefaults(const Locale& locale, StringPiece toFormat, UErrorCode& errorCode);
219     extern DateFormat* defaultDateTimeInstance(const Locale&, UErrorCode&);
220 
221 } // namespace message2
222 
223 U_NAMESPACE_END
224 
225 #endif /* #if !UCONFIG_NO_MF2 */
226 
227 #endif /* #if !UCONFIG_NO_FORMATTING */
228 
229 #endif /* U_SHOW_CPLUSPLUS_API */
230 
231 #endif // MESSAGEFORMAT2_FUNCTION_REGISTRY_INTERNAL_H
232 
233 #endif // U_HIDE_DEPRECATED_API
234 // eof
235