• 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 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