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 MESSAGEFORMAT2_FUNCTION_REGISTRY_H 7 #define MESSAGEFORMAT2_FUNCTION_REGISTRY_H 8 9 #if U_SHOW_CPLUSPLUS_API 10 11 #if !UCONFIG_NO_FORMATTING 12 13 #if !UCONFIG_NO_MF2 14 15 #include "unicode/messageformat2_data_model_names.h" 16 #include "unicode/messageformat2_formattable.h" 17 18 #ifndef U_HIDE_DEPRECATED_API 19 20 #include <map> 21 22 U_NAMESPACE_BEGIN 23 24 class Hashtable; 25 class UVector; 26 27 namespace message2 { 28 29 using namespace data_model; 30 31 /** 32 * Interface that factory classes for creating formatters must implement. 33 * 34 * @internal ICU 75 technology preview 35 * @deprecated This API is for technology preview only. 36 */ 37 class U_I18N_API FormatterFactory : public UObject { 38 // TODO: the coding guidelines say that interface classes 39 // shouldn't inherit from UObject, but if I change it so these 40 // classes don't, and the individual formatter factory classes 41 // inherit from public FormatterFactory, public UObject, then 42 // memory leaks ensue 43 public: 44 /** 45 * Constructs a new formatter object. This method is not const; 46 * formatter factories with local state may be defined. 47 * 48 * @param locale Locale to be used by the formatter. 49 * @param status Input/output error code. 50 * @return The new Formatter, which is non-null if U_SUCCESS(status). 51 * 52 * @internal ICU 75 technology preview 53 * @deprecated This API is for technology preview only. 54 */ 55 virtual Formatter* createFormatter(const Locale& locale, UErrorCode& status) = 0; 56 /** 57 * Destructor. 58 * 59 * @internal ICU 75 technology preview 60 * @deprecated This API is for technology preview only. 61 */ 62 virtual ~FormatterFactory(); 63 /** 64 * Copy constructor. 65 * 66 * @internal ICU 75 technology preview 67 * @deprecated This API is for technology preview only. 68 */ 69 FormatterFactory& operator=(const FormatterFactory&) = delete; 70 }; // class FormatterFactory 71 72 /** 73 * Interface that factory classes for creating selectors must implement. 74 * 75 * @internal ICU 75 technology preview 76 * @deprecated This API is for technology preview only. 77 */ 78 class U_I18N_API SelectorFactory : public UObject { 79 public: 80 /** 81 * Constructs a new selector object. 82 * 83 * @param locale Locale to be used by the selector. 84 * @param status Input/output error code. 85 * @return The new selector, which is non-null if U_SUCCESS(status). 86 * 87 * @internal ICU 75 technology preview 88 * @deprecated This API is for technology preview only. 89 */ 90 virtual Selector* createSelector(const Locale& locale, UErrorCode& status) const = 0; 91 /** 92 * Destructor. 93 * 94 * @internal ICU 75 technology preview 95 * @deprecated This API is for technology preview only. 96 */ 97 virtual ~SelectorFactory(); 98 /** 99 * Copy constructor. 100 * 101 * @internal ICU 75 technology preview 102 * @deprecated This API is for technology preview only. 103 */ 104 SelectorFactory& operator=(const SelectorFactory&) = delete; 105 }; // class SelectorFactory 106 107 /** 108 * Defines mappings from names of formatters and selectors to functions implementing them. 109 * The required set of formatter and selector functions is defined in the spec. Users can 110 * also define custom formatter and selector functions. 111 * 112 * `MFFunctionRegistry` is immutable and movable. It is not copyable. 113 * 114 * @internal ICU 75 technology preview 115 * @deprecated This API is for technology preview only. 116 */ 117 class U_I18N_API MFFunctionRegistry : public UObject { 118 private: 119 120 using FormatterMap = Hashtable; // Map from stringified function names to FormatterFactory* 121 using SelectorMap = Hashtable; // Map from stringified function names to SelectorFactory* 122 123 public: 124 /** 125 * Looks up a formatter factory by the name of the formatter. The result is non-const, 126 * since formatter factories may have local state. Returns the result by pointer 127 * rather than by reference since it can fail. 128 * 129 * @param formatterName Name of the desired formatter. 130 * @return A pointer to the `FormatterFactory` registered under `formatterName`, or null 131 * if no formatter was registered under that name. The pointer is not owned 132 * by the caller. 133 * 134 * @internal ICU 75 technology preview 135 * @deprecated This API is for technology preview only. 136 */ 137 FormatterFactory* getFormatter(const FunctionName& formatterName) const; 138 /** 139 * Looks up a selector factory by the name of the selector. (This returns the result by pointer 140 * rather than by reference since `FormatterFactory` is an abstract class.) 141 * 142 * @param selectorName Name of the desired selector. 143 * @return A pointer to the `SelectorFactory` registered under `selectorName`, or null 144 * if no formatter was registered under that name. 145 * 146 * @internal ICU 75 technology preview 147 * @deprecated This API is for technology preview only. 148 */ 149 const SelectorFactory* getSelector(const FunctionName& selectorName) const; 150 /** 151 * Looks up a formatter factory by a type tag. This method gets the name of the default formatter registered 152 * for that type. If no formatter was explicitly registered for this type, it returns false. 153 * 154 * @param formatterType Type tag for the desired `FormattableObject` type to be formatted. 155 * @param name Output parameter; initialized to the name of the default formatter for `formatterType` 156 * if one has been registered. Its value is undefined otherwise. 157 * @return True if and only if the function registry contains a default formatter for `formatterType`. 158 * If the return value is false, then the value of `name` is undefined. 159 * 160 * @internal ICU 75 technology preview 161 * @deprecated This API is for technology preview only. 162 */ 163 UBool getDefaultFormatterNameByType(const UnicodeString& formatterType, FunctionName& name) const; 164 /** 165 * The mutable Builder class allows each formatter and selector factory 166 * to be initialized separately; calling its `build()` method yields an 167 * immutable MFFunctionRegistry object. 168 * 169 * Builder is not copyable or movable. 170 * 171 * @internal ICU 75 technology preview 172 * @deprecated This API is for technology preview only. 173 */ 174 class U_I18N_API Builder : public UObject { 175 private: 176 // Must use raw pointers to avoid instantiating `LocalPointer` on an internal type 177 FormatterMap* formatters; 178 SelectorMap* selectors; 179 Hashtable* formattersByType; 180 181 // Do not define copy constructor/assignment operator 182 Builder& operator=(const Builder&) = delete; 183 Builder(const Builder&) = delete; 184 185 public: 186 /* 187 Notes about `adoptFormatter()`'s type signature: 188 189 Alternative considered: take a non-owned FormatterFactory* 190 This is unsafe. 191 192 Alternative considered: take a FormatterFactory& 193 This requires getFormatter() to cast the reference to a pointer, 194 as it must return an unowned FormatterFactory* since it can fail. 195 That is also unsafe, since the caller could delete the pointer. 196 197 The "TemperatureFormatter" test from the previous ICU4J version doesn't work now, 198 as it only works if the `formatterFactory` argument is non-owned. 199 If registering a non-owned FormatterFactory is desirable, this could 200 be re-thought. 201 */ 202 /** 203 * Registers a formatter factory to a given formatter name. 204 * 205 * @param formatterName Name of the formatter being registered. 206 * @param formatterFactory A pointer to a FormatterFactory object to use 207 * for creating `formatterName` formatters. This argument is adopted. 208 * @param errorCode Input/output error code 209 * @return A reference to the builder. 210 * 211 * @internal ICU 75 technology preview 212 * @deprecated This API is for technology preview only. 213 */ 214 Builder& adoptFormatter(const data_model::FunctionName& formatterName, FormatterFactory* formatterFactory, UErrorCode& errorCode); 215 /** 216 * Registers a formatter factory to a given type tag. 217 * (See `FormattableObject` for details on type tags.) 218 * 219 * @param type Tag for objects to be formatted with this formatter. 220 * @param functionName A reference to the name of the function to use for 221 * creating formatters for `formatterType` objects. 222 * @param errorCode Input/output error code 223 * @return A reference to the builder. 224 * 225 * @internal ICU 75 technology preview 226 * @deprecated This API is for technology preview only. 227 */ 228 Builder& setDefaultFormatterNameByType(const UnicodeString& type, const data_model::FunctionName& functionName, UErrorCode& errorCode); 229 230 /** 231 * Registers a selector factory to a given selector name. Adopts `selectorFactory`. 232 * 233 * @param selectorName Name of the selector being registered. 234 * @param selectorFactory A SelectorFactory object to use for creating `selectorName` 235 * selectors. 236 * @param errorCode Input/output error code 237 * @return A reference to the builder. 238 * 239 * @internal ICU 75 technology preview 240 * @deprecated This API is for technology preview only. 241 */ 242 Builder& adoptSelector(const data_model::FunctionName& selectorName, SelectorFactory* selectorFactory, UErrorCode& errorCode); 243 /** 244 * Creates an immutable `MFFunctionRegistry` object with the selectors and formatters 245 * that were previously registered. The builder cannot be used after this call. 246 * The `build()` method is destructive to avoid the need for a deep copy of the 247 * `FormatterFactory` and `SelectorFactory` objects (this would be necessary because 248 * `FormatterFactory` can have mutable state), which in turn would require implementors 249 * of those interfaces to implement a `clone()` method. 250 * 251 * @return The new MFFunctionRegistry 252 * 253 * @internal ICU 75 technology preview 254 * @deprecated This API is for technology preview only. 255 */ 256 MFFunctionRegistry build(); 257 /** 258 * Default constructor. 259 * Returns a Builder with no functions registered. 260 * 261 * @param errorCode Input/output error code 262 * 263 * @internal ICU 75 technology preview 264 * @deprecated This API is for technology preview only. 265 */ 266 Builder(UErrorCode& errorCode); 267 /** 268 * Destructor. 269 * 270 * @internal ICU 75 technology preview 271 * @deprecated This API is for technology preview only. 272 */ 273 virtual ~Builder(); 274 }; // class MFFunctionRegistry::Builder 275 276 /** 277 * Move assignment operator: 278 * The source MFFunctionRegistry will be left in a valid but undefined state. 279 * 280 * @internal ICU 75 technology preview 281 * @deprecated This API is for technology preview only. 282 */ 283 MFFunctionRegistry& operator=(MFFunctionRegistry&&) noexcept; 284 /** 285 * Move constructor: 286 * The source MFFunctionRegistry will be left in a valid but undefined state. 287 * 288 * @internal ICU 75 technology preview 289 * @deprecated This API is for technology preview only. 290 */ MFFunctionRegistry(MFFunctionRegistry && other)291 MFFunctionRegistry(MFFunctionRegistry&& other) { *this = std::move(other); } 292 /** 293 * Destructor. 294 * 295 * @internal ICU 75 technology preview 296 * @deprecated This API is for technology preview only. 297 */ 298 virtual ~MFFunctionRegistry(); 299 300 private: 301 friend class MessageContext; 302 friend class MessageFormatter; 303 304 // Do not define copy constructor or copy assignment operator 305 MFFunctionRegistry& operator=(const MFFunctionRegistry&) = delete; 306 MFFunctionRegistry(const MFFunctionRegistry&) = delete; 307 308 MFFunctionRegistry(FormatterMap* f, SelectorMap* s, Hashtable* byType); 309 MFFunctionRegistry()310 MFFunctionRegistry() {} 311 312 // Debugging; should only be called on a function registry with 313 // all the standard functions registered 314 void checkFormatter(const char*) const; 315 void checkSelector(const char*) const; 316 void checkStandard() const; 317 318 bool hasFormatter(const data_model::FunctionName& f) const; 319 bool hasSelector(const data_model::FunctionName& s) const; 320 void cleanup() noexcept; 321 322 // Must use raw pointers to avoid instantiating `LocalPointer` on an internal type 323 FormatterMap* formatters = nullptr; 324 SelectorMap* selectors = nullptr; 325 // Mapping from strings (type tags) to FunctionNames 326 Hashtable* formattersByType = nullptr; 327 }; // class MFFunctionRegistry 328 329 /** 330 * Interface that formatter classes must implement. 331 * 332 * @internal ICU 75 technology preview 333 * @deprecated This API is for technology preview only. 334 */ 335 class U_I18N_API Formatter : public UObject { 336 public: 337 /** 338 * Formats the input passed in `context` by setting an output using one of the 339 * `FormattingContext` methods or indicating an error. 340 * 341 * @param toFormat Placeholder, including a source formattable value and possibly 342 * the output of a previous formatter applied to it; see 343 * `message2::FormattedPlaceholder` for details. Passed by move. 344 * @param options The named function options. Passed by move 345 * @param status Input/output error code. Should not be set directly by the 346 * custom formatter, which should use `FormattingContext::setFormattingWarning()` 347 * to signal errors. The custom formatter may pass `status` to other ICU functions 348 * that can signal errors using this mechanism. 349 * 350 * @return The formatted value. 351 * 352 * @internal ICU 75 technology preview 353 * @deprecated This API is for technology preview only. 354 */ 355 virtual FormattedPlaceholder format(FormattedPlaceholder&& toFormat, 356 FunctionOptions&& options, 357 UErrorCode& status) const = 0; 358 /** 359 * Destructor. 360 * 361 * @internal ICU 75 technology preview 362 * @deprecated This API is for technology preview only. 363 */ 364 virtual ~Formatter(); 365 }; // class Formatter 366 367 /** 368 * Interface that selector classes must implement. 369 * 370 * @internal ICU 75 technology preview 371 * @deprecated This API is for technology preview only. 372 */ 373 class U_I18N_API Selector : public UObject { 374 public: 375 /** 376 * Compares the input to an array of keys, and returns an array of matching 377 * keys sorted by preference. 378 * 379 * @param toFormat The unnamed function argument; passed by move. 380 * @param options A reference to the named function options. 381 * @param keys An array of strings that are compared to the input 382 * (`context.getFormattableInput()`) in an implementation-specific way. 383 * @param keysLen The length of `keys`. 384 * @param prefs An array of strings with length `keysLen`. The contents of 385 * the array is undefined. `selectKey()` should set the contents 386 * of `prefs` to a subset of `keys`, with the best match placed at the lowest index. 387 * @param prefsLen A reference that `selectKey()` should set to the length of `prefs`, 388 * which must be less than or equal to `keysLen`. 389 * @param status Input/output error code. Should not be set directly by the 390 * custom selector, which should use `FormattingContext::setSelectorError()` 391 * to signal errors. The custom selector may pass `status` to other ICU functions 392 * that can signal errors using this mechanism. 393 * 394 * @internal ICU 75 technology preview 395 * @deprecated This API is for technology preview only. 396 */ 397 virtual void selectKey(FormattedPlaceholder&& toFormat, 398 FunctionOptions&& options, 399 const UnicodeString* keys, 400 int32_t keysLen, 401 UnicodeString* prefs, 402 int32_t& prefsLen, 403 UErrorCode& status) const = 0; 404 // Note: This takes array arguments because the internal MessageFormat code has to 405 // call this method, and can't include any code that constructs std::vectors. 406 /** 407 * Destructor. 408 * 409 * @internal ICU 75 technology preview 410 * @deprecated This API is for technology preview only. 411 */ 412 virtual ~Selector(); 413 }; // class Selector 414 415 } // namespace message2 416 417 U_NAMESPACE_END 418 419 #endif // U_HIDE_DEPRECATED_API 420 421 #endif /* #if !UCONFIG_NO_MF2 */ 422 423 #endif /* #if !UCONFIG_NO_FORMATTING */ 424 425 #endif /* U_SHOW_CPLUSPLUS_API */ 426 427 #endif // MESSAGEFORMAT2_FUNCTION_REGISTRY_H 428 429 // eof 430