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