ICU 75.1  75.1
messageformat2.h
Go to the documentation of this file.
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_H
7 #define MESSAGEFORMAT2_H
8 
9 #if U_SHOW_CPLUSPLUS_API
10 
11 #if !UCONFIG_NO_FORMATTING
12 
13 #if !UCONFIG_NO_MF2
14 
21 #include "unicode/messageformat2_data_model.h"
22 #include "unicode/messageformat2_function_registry.h"
23 #include "unicode/unistr.h"
24 
25 #ifndef U_HIDE_DEPRECATED_API
26 
27 U_NAMESPACE_BEGIN
28 
29 namespace message2 {
30 
31  class Environment;
32  class MessageContext;
33  class ResolvedSelector;
34  class StaticErrors;
35 
52  // Note: This class does not currently inherit from the existing
53  // `Format` class.
54  public:
69  virtual ~MessageFormatter();
70 
85  UnicodeString formatToString(const MessageArguments& arguments, UErrorCode &status);
86 
102  FormattedMessage format(const MessageArguments& arguments, UErrorCode &status) const {
103  (void) arguments;
104  if (U_SUCCESS(status)) {
105  status = U_UNSUPPORTED_ERROR;
106  }
107  return FormattedMessage(status);
108  }
109 
118  const Locale& getLocale() const { return locale; }
119 
130 
140  const MFDataModel& getDataModel() const;
141 
148  class U_I18N_API Builder : public UObject {
149  private:
150  friend class MessageFormatter;
151 
152  // The pattern to be parsed to generate the formatted message
153  UnicodeString pattern;
154  bool hasPattern = false;
155  bool hasDataModel = false;
156  // The data model to be used to generate the formatted message
157  // Initialized either by `setDataModel()`, or by the parser
158  // through a call to `setPattern()`
159  MFDataModel dataModel;
160  // Normalized representation of the pattern;
161  // ignored if `setPattern()` wasn't called
162  UnicodeString normalizedInput;
163  // Errors (internal representation of parse errors)
164  // Ignored if `setPattern()` wasn't called
165  StaticErrors* errors;
166  Locale locale;
167  // Not owned
168  const MFFunctionRegistry* customMFFunctionRegistry;
169 
170  public:
180  Builder& setLocale(const Locale& locale);
196  Builder& setPattern(const UnicodeString& pattern, UParseError& parseError, UErrorCode& status);
210  Builder& setFunctionRegistry(const MFFunctionRegistry& functionRegistry);
247  Builder(UErrorCode& status);
254  virtual ~Builder();
255  }; // class MessageFormatter::Builder
256 
257  // TODO: Shouldn't be public; only used for testing
266  const UnicodeString& getNormalizedPattern() const { return normalizedInput; }
267 
268  private:
269  friend class Builder;
270  friend class MessageContext;
271 
272  MessageFormatter(const MessageFormatter::Builder& builder, UErrorCode &status);
273 
274  MessageFormatter() = delete; // default constructor not implemented
275 
276  // Do not define default assignment operator
277  const MessageFormatter &operator=(const MessageFormatter &) = delete;
278 
279  ResolvedSelector resolveVariables(const Environment& env, const data_model::Operand&, MessageContext&, UErrorCode &) const;
280  ResolvedSelector resolveVariables(const Environment& env, const data_model::Expression&, MessageContext&, UErrorCode &) const;
281 
282  // Selection methods
283 
284  // Takes a vector of FormattedPlaceholders
285  void resolveSelectors(MessageContext&, const Environment& env, UErrorCode&, UVector&) const;
286  // Takes a vector of vectors of strings (input) and a vector of PrioritizedVariants (output)
287  void filterVariants(const UVector&, UVector&, UErrorCode&) const;
288  // Takes a vector of vectors of strings (input) and a vector of PrioritizedVariants (input/output)
289  void sortVariants(const UVector&, UVector&, UErrorCode&) const;
290  // Takes a vector of strings (input) and a vector of strings (output)
291  void matchSelectorKeys(const UVector&, MessageContext&, ResolvedSelector&& rv, UVector&, UErrorCode&) const;
292  // Takes a vector of FormattedPlaceholders (input),
293  // and a vector of vectors of strings (output)
294  void resolvePreferences(MessageContext&, UVector&, UVector&, UErrorCode&) const;
295 
296  // Formatting methods
297  [[nodiscard]] FormattedPlaceholder formatLiteral(const data_model::Literal&) const;
298  void formatPattern(MessageContext&, const Environment&, const data_model::Pattern&, UErrorCode&, UnicodeString&) const;
299  // Formats a call to a formatting function
300  // Dispatches on argument type
301  [[nodiscard]] FormattedPlaceholder evalFormatterCall(FormattedPlaceholder&& argument,
302  MessageContext& context,
303  UErrorCode& status) const;
304  // Dispatches on function name
305  [[nodiscard]] FormattedPlaceholder evalFormatterCall(const FunctionName& functionName,
306  FormattedPlaceholder&& argument,
307  FunctionOptions&& options,
308  MessageContext& context,
309  UErrorCode& status) const;
310  // Formats an expression that appears as a selector
311  ResolvedSelector formatSelectorExpression(const Environment& env, const data_model::Expression&, MessageContext&, UErrorCode&) const;
312  // Formats an expression that appears in a pattern or as the definition of a local variable
313  [[nodiscard]] FormattedPlaceholder formatExpression(const Environment&, const data_model::Expression&, MessageContext&, UErrorCode&) const;
314  [[nodiscard]] FunctionOptions resolveOptions(const Environment& env, const OptionMap&, MessageContext&, UErrorCode&) const;
315  [[nodiscard]] FormattedPlaceholder formatOperand(const Environment&, const data_model::Operand&, MessageContext&, UErrorCode&) const;
316  [[nodiscard]] FormattedPlaceholder evalArgument(const data_model::VariableName&, MessageContext&, UErrorCode&) const;
317  void formatSelectors(MessageContext& context, const Environment& env, UErrorCode &status, UnicodeString& result) const;
318 
319  // Function registry methods
320  bool hasCustomMFFunctionRegistry() const {
321  return (customMFFunctionRegistry != nullptr);
322  }
323 
324  // Precondition: custom function registry exists
325  // Note: this is non-const because the values in the MFFunctionRegistry are mutable
326  // (a FormatterFactory can have mutable state)
327  const MFFunctionRegistry& getCustomMFFunctionRegistry() const;
328 
329  bool isCustomFormatter(const FunctionName&) const;
330  FormatterFactory* lookupFormatterFactory(const FunctionName&, UErrorCode& status) const;
331  bool isBuiltInSelector(const FunctionName&) const;
332  bool isBuiltInFormatter(const FunctionName&) const;
333  bool isCustomSelector(const FunctionName&) const;
334  const SelectorFactory* lookupSelectorFactory(MessageContext&, const FunctionName&, UErrorCode&) const;
335  bool isSelector(const FunctionName& fn) const { return isBuiltInSelector(fn) || isCustomSelector(fn); }
336  bool isFormatter(const FunctionName& fn) const { return isBuiltInFormatter(fn) || isCustomFormatter(fn); }
337  const Formatter* lookupFormatter(const FunctionName&, UErrorCode&) const;
338 
339  Selector* getSelector(MessageContext&, const FunctionName&, UErrorCode&) const;
340  Formatter* getFormatter(const FunctionName&, UErrorCode&) const;
341  bool getDefaultFormatterNameByType(const UnicodeString&, FunctionName&) const;
342 
343  // Checking for resolution errors
344  void checkDeclarations(MessageContext&, Environment*&, UErrorCode&) const;
345  void check(MessageContext&, const Environment&, const data_model::Expression&, UErrorCode&) const;
346  void check(MessageContext&, const Environment&, const data_model::Operand&, UErrorCode&) const;
347  void check(MessageContext&, const Environment&, const OptionMap&, UErrorCode&) const;
348 
349  void initErrors(UErrorCode&);
350  void clearErrors() const;
351  void cleanup() noexcept;
352 
353  // The locale this MessageFormatter was created with
354  /* const */ Locale locale;
355 
356  // Registry for built-in functions
357  MFFunctionRegistry standardMFFunctionRegistry;
358  // Registry for custom functions; may be null if no custom registry supplied
359  // Note: this is *not* owned by the MessageFormatter object
360  // The reason for this choice is to have a non-destructive MessageFormatter::Builder,
361  // while also not requiring the function registry to be deeply-copyable. Making the
362  // function registry copyable would impose a requirement on any implementations
363  // of the FormatterFactory and SelectorFactory interfaces to implement a custom
364  // clone() method, which is necessary to avoid sharing between copies of the
365  // function registry (and thus double-frees)
366  // Not deeply immutable (the values in the function registry are mutable,
367  // as a FormatterFactory can have mutable state
368  const MFFunctionRegistry* customMFFunctionRegistry;
369 
370  // Data model, representing the parsed message
371  MFDataModel dataModel;
372 
373  // Normalized version of the input string (optional whitespace removed)
374  UnicodeString normalizedInput;
375 
376  // Errors -- only used while parsing and checking for data model errors; then
377  // the MessageContext keeps track of errors
378  // Must be a raw pointer to avoid including the internal header file
379  // defining StaticErrors
380  // Owned by `this`
381  StaticErrors* errors;
382 
383  }; // class MessageFormatter
384 
385 } // namespace message2
386 
387 U_NAMESPACE_END
388 
389 #endif // U_HIDE_DEPRECATED_API
390 
391 #endif /* #if !UCONFIG_NO_MF2 */
392 
393 #endif /* #if !UCONFIG_NO_FORMATTING */
394 
395 #endif /* U_SHOW_CPLUSPLUS_API */
396 
397 #endif // MESSAGEFORMAT2_H
398 
399 // eof
A Locale object represents a specific geographical, political, or cultural region.
Definition: locid.h:195
UObject is the common ICU "boilerplate" class.
Definition: uobject.h:223
UnicodeString is a string class that stores Unicode characters directly and provides similar function...
Definition: unistr.h:296
Not yet implemented: The result of a message formatting operation.
A FormattablePlaceholder encapsulates an input value (a message2::Formattable) together with an optio...
Structure encapsulating named options passed to a custom selector or formatter.
The MFDataModel class describes a parsed representation of the text of a message.
Defines mappings from names of formatters and selectors to functions implementing them.
The MessageArguments class represents the named arguments to a message.
The mutable Builder class allows each part of the MessageFormatter to be initialized separately; call...
Builder & setPattern(const UnicodeString &pattern, UParseError &parseError, UErrorCode &status)
Sets the pattern (contents of the message) and parses it into a data model.
MessageFormatter build(UErrorCode &status) const
Constructs a new immutable MessageFormatter using the pattern or data model that was previously set,...
Builder(UErrorCode &status)
Default constructor.
Builder & setDataModel(MFDataModel &&dataModel)
Sets a data model.
Builder & setFunctionRegistry(const MFFunctionRegistry &functionRegistry)
Sets a custom function registry.
Builder & setLocale(const Locale &locale)
Sets the locale to use for formatting.
const UnicodeString & getNormalizedPattern() const
Returns a string consisting of the input with optional spaces removed.
const Locale & getLocale() const
Accesses the locale that this MessageFormatter object was created with.
UnicodeString getPattern() const
Serializes the data model as a string in MessageFormat 2.0 syntax.
const MFDataModel & getDataModel() const
Accesses the data model referred to by this MessageFormatter object.
MessageFormatter & operator=(MessageFormatter &&) noexcept
Move assignment operator: The source MessageFormatter will be left in a valid but undefined state.
The Expression class corresponds to the expression nonterminal in the MessageFormat 2 grammar and the...
The Literal class corresponds to the literal nonterminal in the MessageFormat 2 grammar,...
The Operand class corresponds to the operand nonterminal in the MessageFormat 2 grammar,...
A Pattern is a sequence of formattable parts.
C++ API: Formats messages using the draft MessageFormat 2.0.
A UParseError struct is used to returned detailed information about parsing errors.
Definition: parseerr.h:58
C++ API: Unicode String.
Basic definitions for ICU, for both C and C++ APIs.
UErrorCode
Standard ICU4C error code type, a substitute for exceptions.
Definition: utypes.h:415
@ U_UNSUPPORTED_ERROR
Requested operation not supported in current context.
Definition: utypes.h:467
#define U_SUCCESS(x)
Does the error code indicate success?
Definition: utypes.h:728
#define U_I18N_API
Set to export library symbols from inside the i18n library, and to import them from outside.
Definition: utypes.h:301