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