Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-01-07 10:23:59

0001 // © 2024 and later: Unicode, Inc. and others.
0002 // License & terms of use: http://www.unicode.org/copyright.html
0003 
0004 #include "unicode/utypes.h"
0005 
0006 #ifndef MESSAGEFORMAT2_H
0007 #define MESSAGEFORMAT2_H
0008 
0009 #if U_SHOW_CPLUSPLUS_API
0010 
0011 #if !UCONFIG_NO_FORMATTING
0012 
0013 #if !UCONFIG_NO_MF2
0014 
0015 /**
0016  * \file
0017  * \brief C++ API: Formats messages using the draft MessageFormat 2.0.
0018  */
0019 
0020 #include "unicode/messageformat2_arguments.h"
0021 #include "unicode/messageformat2_data_model.h"
0022 #include "unicode/messageformat2_function_registry.h"
0023 #include "unicode/unistr.h"
0024 
0025 #ifndef U_HIDE_DEPRECATED_API
0026 
0027 U_NAMESPACE_BEGIN
0028 
0029 namespace message2 {
0030 
0031     class Environment;
0032     class MessageContext;
0033     class ResolvedSelector;
0034     class StaticErrors;
0035 
0036     /**
0037      * <p>MessageFormatter is a Technical Preview API implementing MessageFormat 2.0.
0038      *
0039      * <p>See <a target="github" href="https://github.com/unicode-org/message-format-wg/blob/main/spec/syntax.md">the
0040      * description of the syntax with examples and use cases</a> and the corresponding
0041      * <a target="github" href="https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf">ABNF</a> grammar.</p>
0042      *
0043      * The MessageFormatter class is mutable and movable. It is not copyable.
0044      * (It is mutable because if it has a custom function registry, the registry may include
0045      * `FormatterFactory` objects implementing custom formatters, which are allowed to contain
0046      * mutable state.)
0047      *
0048      * @internal ICU 75 technology preview
0049      * @deprecated This API is for technology preview only.
0050      */
0051     class U_I18N_API MessageFormatter : public UObject {
0052         // Note: This class does not currently inherit from the existing
0053         // `Format` class.
0054     public:
0055         /**
0056          * Move assignment operator:
0057          * The source MessageFormatter will be left in a valid but undefined state.
0058          *
0059          * @internal ICU 75 technology preview
0060          * @deprecated This API is for technology preview only.
0061          */
0062         MessageFormatter& operator=(MessageFormatter&&) noexcept;
0063         /**
0064          * Destructor.
0065          *
0066          * @internal ICU 75 technology preview
0067          * @deprecated This API is for technology preview only.
0068          */
0069         virtual ~MessageFormatter();
0070 
0071         /**
0072          * Formats the message to a string, using the data model that was previously set or parsed,
0073          * and the given `arguments` object.
0074          *
0075          * @param arguments Reference to message arguments
0076          * @param status    Input/output error code used to indicate syntax errors, data model
0077          *                  errors, resolution errors, formatting errors, selection errors, as well
0078          *                  as other errors (such as memory allocation failures). Partial output
0079          *                  is still provided in the presence of most error types.
0080          * @return          The string result of formatting the message with the given arguments.
0081          *
0082          * @internal ICU 75 technology preview
0083          * @deprecated This API is for technology preview only.
0084          */
0085         UnicodeString formatToString(const MessageArguments& arguments, UErrorCode &status);
0086 
0087         /**
0088          * Not yet implemented; formats the message to a `FormattedMessage` object,
0089          * using the data model that was previously set or parsed,
0090          * and the given `arguments` object.
0091          *
0092          * @param arguments Reference to message arguments
0093          * @param status    Input/output error code used to indicate syntax errors, data model
0094          *                  errors, resolution errors, formatting errors, selection errors, as well
0095          *                  as other errors (such as memory allocation failures). Partial output
0096          *                  is still provided in the presence of most error types.
0097          * @return          The `FormattedMessage` representing the formatted message.
0098          *
0099          * @internal ICU 75 technology preview
0100          * @deprecated This API is for technology preview only.
0101          */
0102         FormattedMessage format(const MessageArguments& arguments, UErrorCode &status) const {
0103             (void) arguments;
0104             if (U_SUCCESS(status)) {
0105                 status = U_UNSUPPORTED_ERROR;
0106             }
0107             return FormattedMessage(status);
0108         }
0109 
0110         /**
0111          * Accesses the locale that this `MessageFormatter` object was created with.
0112          *
0113          * @return A reference to the locale.
0114          *
0115          * @internal ICU 75 technology preview
0116          * @deprecated This API is for technology preview only.
0117          */
0118         const Locale& getLocale() const { return locale; }
0119 
0120         /**
0121          * Serializes the data model as a string in MessageFormat 2.0 syntax.
0122          *
0123          * @return result    A string representation of the data model.
0124          *                   The string is a valid MessageFormat 2.0 message.
0125          *
0126          * @internal ICU 75 technology preview
0127          * @deprecated This API is for technology preview only.
0128          */
0129         UnicodeString getPattern() const;
0130 
0131         /**
0132          * Accesses the data model referred to by this
0133          * `MessageFormatter` object.
0134          *
0135          * @return A reference to the data model.
0136          *
0137          * @internal ICU 75 technology preview
0138          * @deprecated This API is for technology preview only.
0139          */
0140         const MFDataModel& getDataModel() const;
0141 
0142         /**
0143          * Used in conjunction with the
0144          * MessageFormatter::Builder::setErrorHandlingBehavior() method.
0145          *
0146          * @internal ICU 76 technology preview
0147          * @deprecated This API is for technology preview only.
0148          */
0149         typedef enum UMFErrorHandlingBehavior {
0150             /**
0151              * Suppress errors and return best-effort output.
0152              *
0153              * @internal ICU 76 technology preview
0154              * @deprecated This API is for technology preview only.
0155              */
0156             U_MF_BEST_EFFORT = 0,
0157             /**
0158              * Signal all MessageFormat errors using the UErrorCode
0159              * argument.
0160              *
0161              * @internal ICU 76 technology preview
0162              * @deprecated This API is for technology preview only.
0163              */
0164             U_MF_STRICT
0165         } UMFErrorHandlingBehavior;
0166 
0167         /**
0168          * The mutable Builder class allows each part of the MessageFormatter to be initialized
0169          * separately; calling its `build()` method yields an immutable MessageFormatter.
0170          *
0171          * Not copyable or movable.
0172          */
0173         class U_I18N_API Builder : public UObject {
0174         private:
0175             friend class MessageFormatter;
0176 
0177             // The pattern to be parsed to generate the formatted message
0178             UnicodeString pattern;
0179             bool hasPattern = false;
0180             bool hasDataModel = false;
0181             // The data model to be used to generate the formatted message
0182             // Initialized either by `setDataModel()`, or by the parser
0183             // through a call to `setPattern()`
0184             MFDataModel dataModel;
0185             // Normalized representation of the pattern;
0186             // ignored if `setPattern()` wasn't called
0187             UnicodeString normalizedInput;
0188             // Errors (internal representation of parse errors)
0189             // Ignored if `setPattern()` wasn't called
0190             StaticErrors* errors;
0191             Locale locale;
0192             // Not owned
0193             const MFFunctionRegistry* customMFFunctionRegistry;
0194             // Error behavior; see comment in `MessageFormatter` class
0195             bool signalErrors = false;
0196 
0197             void clearState();
0198         public:
0199             /**
0200              * Sets the locale to use for formatting.
0201              *
0202              * @param locale The desired locale.
0203              * @return       A reference to the builder.
0204              *
0205              * @internal ICU 75 technology preview
0206              * @deprecated This API is for technology preview only.
0207              */
0208             Builder& setLocale(const Locale& locale);
0209             /**
0210              * Sets the pattern (contents of the message) and parses it
0211              * into a data model. If a data model was
0212              * previously set, it is removed.
0213              *
0214              * @param pattern A string in MessageFormat 2.0 syntax.
0215              * @param parseError Struct to receive information on the position
0216              *                   of an error within the pattern.
0217              * @param status    Input/output error code. If the
0218              *                  pattern cannot be parsed, set to failure code.
0219              * @return       A reference to the builder.
0220              *
0221              * @internal ICU 75 technology preview
0222              * @deprecated This API is for technology preview only.
0223              */
0224             Builder& setPattern(const UnicodeString& pattern, UParseError& parseError, UErrorCode& status);
0225             /**
0226              * Sets a custom function registry.
0227              *
0228              * @param functionRegistry Reference to the function registry to use.
0229              *        `functionRegistry` is not copied,
0230              *        and the caller must ensure its lifetime contains
0231              *        the lifetime of the `MessageFormatter` object built by this
0232              *        builder.
0233              * @return       A reference to the builder.
0234              *
0235              * @internal ICU 75 technology preview
0236              * @deprecated This API is for technology preview only.
0237              */
0238             Builder& setFunctionRegistry(const MFFunctionRegistry& functionRegistry);
0239             /**
0240              * Sets a data model. If a pattern was previously set, it is removed.
0241              *
0242              * @param dataModel Data model to format. Passed by move.
0243              * @return       A reference to the builder.
0244              *
0245              * @internal ICU 75 technology preview
0246              * @deprecated This API is for technology preview only.
0247              */
0248             Builder& setDataModel(MFDataModel&& dataModel);
0249             /**
0250              * Set the error handling behavior for this formatter.
0251              *
0252              * "Strict" error behavior means that that formatting methods
0253              * will set their UErrorCode arguments to signal MessageFormat
0254              * data model, resolution, and runtime errors. Syntax errors are
0255              * always signaled.
0256              *
0257              * "Best effort" error behavior means that MessageFormat errors are
0258              * suppressed:  formatting methods will _not_ set their
0259              * UErrorCode arguments to signal MessageFormat data model,
0260              * resolution, or runtime errors. Best-effort output
0261              * will be returned. Syntax errors are always signaled.
0262              * This is the default behavior.
0263              *
0264              * @param type An enum with type UMFErrorHandlingBehavior;
0265              *             if type == `U_MF_STRICT`, then
0266              *             errors are handled strictly.
0267              *             If type == `U_MF_BEST_EFFORT`, then
0268              *             best-effort output is returned.
0269              *
0270              * The default is to suppress all MessageFormat errors
0271              * and return best-effort output.
0272              *
0273              * @return       A reference to the builder.
0274              *
0275              * @internal ICU 76 technology preview
0276              * @deprecated This API is for technology preview only.
0277              */
0278             Builder& setErrorHandlingBehavior(UMFErrorHandlingBehavior type);
0279             /**
0280              * Constructs a new immutable MessageFormatter using the pattern or data model
0281              * that was previously set, and the locale (if it was previously set)
0282              * or default locale (otherwise).
0283              *
0284              * The builder object (`this`) can still be used after calling `build()`.
0285              *
0286              * @param status    Input/output error code.  If neither the pattern
0287              *                  nor the data model is set, set to failure code.
0288              * @return          The new MessageFormatter object
0289              *
0290              * @internal ICU 75 technology preview
0291              * @deprecated This API is for technology preview only.
0292              */
0293             MessageFormatter build(UErrorCode& status) const;
0294             /**
0295              * Default constructor.
0296              * Returns a Builder with the default locale and with no
0297              * data model or pattern set. Either `setPattern()`
0298              * or `setDataModel()` has to be called before calling `build()`.
0299              *
0300              * @param status    Input/output error code.
0301              *
0302              * @internal ICU 75 technology preview
0303              * @deprecated This API is for technology preview only.
0304              */
0305             Builder(UErrorCode& status);
0306             /**
0307              * Destructor.
0308              *
0309              * @internal ICU 75 technology preview
0310              * @deprecated This API is for technology preview only.
0311              */
0312             virtual ~Builder();
0313         }; // class MessageFormatter::Builder
0314 
0315         // TODO: Shouldn't be public; only used for testing
0316         /**
0317          * Returns a string consisting of the input with optional spaces removed.
0318          *
0319          * @return        A normalized string representation of the input
0320          *
0321          * @internal ICU 75 technology preview
0322          * @deprecated This API is for technology preview only.
0323          */
0324         const UnicodeString& getNormalizedPattern() const { return normalizedInput; }
0325 
0326     private:
0327         friend class Builder;
0328         friend class MessageContext;
0329 
0330         MessageFormatter(const MessageFormatter::Builder& builder, UErrorCode &status);
0331 
0332         MessageFormatter() = delete; // default constructor not implemented
0333 
0334         // Do not define default assignment operator
0335         const MessageFormatter &operator=(const MessageFormatter &) = delete;
0336 
0337         ResolvedSelector resolveVariables(const Environment& env, const data_model::Operand&, MessageContext&, UErrorCode &) const;
0338         ResolvedSelector resolveVariables(const Environment& env, const data_model::Expression&, MessageContext&, UErrorCode &) const;
0339 
0340         // Selection methods
0341 
0342         // Takes a vector of FormattedPlaceholders
0343         void resolveSelectors(MessageContext&, const Environment& env, UErrorCode&, UVector&) const;
0344         // Takes a vector of vectors of strings (input) and a vector of PrioritizedVariants (output)
0345         void filterVariants(const UVector&, UVector&, UErrorCode&) const;
0346         // Takes a vector of vectors of strings (input) and a vector of PrioritizedVariants (input/output)
0347         void sortVariants(const UVector&, UVector&, UErrorCode&) const;
0348         // Takes a vector of strings (input) and a vector of strings (output)
0349         void matchSelectorKeys(const UVector&, MessageContext&, ResolvedSelector&& rv, UVector&, UErrorCode&) const;
0350         // Takes a vector of FormattedPlaceholders (input),
0351         // and a vector of vectors of strings (output)
0352         void resolvePreferences(MessageContext&, UVector&, UVector&, UErrorCode&) const;
0353 
0354         // Formatting methods
0355         [[nodiscard]] FormattedPlaceholder formatLiteral(const data_model::Literal&) const;
0356         void formatPattern(MessageContext&, const Environment&, const data_model::Pattern&, UErrorCode&, UnicodeString&) const;
0357         // Formats a call to a formatting function
0358         // Dispatches on argument type
0359         [[nodiscard]] FormattedPlaceholder evalFormatterCall(FormattedPlaceholder&& argument,
0360                                                        MessageContext& context,
0361                                                        UErrorCode& status) const;
0362         // Dispatches on function name
0363         [[nodiscard]] FormattedPlaceholder evalFormatterCall(const FunctionName& functionName,
0364                                                        FormattedPlaceholder&& argument,
0365                                                        FunctionOptions&& options,
0366                                                        MessageContext& context,
0367                                                        UErrorCode& status) const;
0368         // Formats an expression that appears as a selector
0369         ResolvedSelector formatSelectorExpression(const Environment& env, const data_model::Expression&, MessageContext&, UErrorCode&) const;
0370         // Formats an expression that appears in a pattern or as the definition of a local variable
0371         [[nodiscard]] FormattedPlaceholder formatExpression(const Environment&, const data_model::Expression&, MessageContext&, UErrorCode&) const;
0372         [[nodiscard]] FunctionOptions resolveOptions(const Environment& env, const OptionMap&, MessageContext&, UErrorCode&) const;
0373         [[nodiscard]] FormattedPlaceholder formatOperand(const Environment&, const data_model::Operand&, MessageContext&, UErrorCode&) const;
0374         [[nodiscard]] FormattedPlaceholder evalArgument(const data_model::VariableName&, MessageContext&, UErrorCode&) const;
0375         void formatSelectors(MessageContext& context, const Environment& env, UErrorCode &status, UnicodeString& result) const;
0376 
0377         // Function registry methods
0378         bool hasCustomMFFunctionRegistry() const {
0379             return (customMFFunctionRegistry != nullptr);
0380         }
0381 
0382         // Precondition: custom function registry exists
0383         // Note: this is non-const because the values in the MFFunctionRegistry are mutable
0384         // (a FormatterFactory can have mutable state)
0385         const MFFunctionRegistry& getCustomMFFunctionRegistry() const;
0386 
0387         bool isCustomFormatter(const FunctionName&) const;
0388         FormatterFactory* lookupFormatterFactory(const FunctionName&, UErrorCode& status) const;
0389         bool isBuiltInSelector(const FunctionName&) const;
0390         bool isBuiltInFormatter(const FunctionName&) const;
0391         bool isCustomSelector(const FunctionName&) const;
0392         const SelectorFactory* lookupSelectorFactory(MessageContext&, const FunctionName&, UErrorCode&) const;
0393         bool isSelector(const FunctionName& fn) const { return isBuiltInSelector(fn) || isCustomSelector(fn); }
0394         bool isFormatter(const FunctionName& fn) const { return isBuiltInFormatter(fn) || isCustomFormatter(fn); }
0395         const Formatter* lookupFormatter(const FunctionName&, UErrorCode&) const;
0396 
0397         Selector* getSelector(MessageContext&, const FunctionName&, UErrorCode&) const;
0398         Formatter* getFormatter(const FunctionName&, UErrorCode&) const;
0399         bool getDefaultFormatterNameByType(const UnicodeString&, FunctionName&) const;
0400 
0401         // Checking for resolution errors
0402         void checkDeclarations(MessageContext&, Environment*&, UErrorCode&) const;
0403         void check(MessageContext&, const Environment&, const data_model::Expression&, UErrorCode&) const;
0404         void check(MessageContext&, const Environment&, const data_model::Operand&, UErrorCode&) const;
0405         void check(MessageContext&, const Environment&, const OptionMap&, UErrorCode&) const;
0406 
0407         void initErrors(UErrorCode&);
0408         void clearErrors() const;
0409         void cleanup() noexcept;
0410 
0411         // The locale this MessageFormatter was created with
0412         /* const */ Locale locale;
0413 
0414         // Registry for built-in functions
0415         MFFunctionRegistry standardMFFunctionRegistry;
0416         // Registry for custom functions; may be null if no custom registry supplied
0417         // Note: this is *not* owned by the MessageFormatter object
0418         // The reason for this choice is to have a non-destructive MessageFormatter::Builder,
0419         // while also not requiring the function registry to be deeply-copyable. Making the
0420         // function registry copyable would impose a requirement on any implementations
0421         // of the FormatterFactory and SelectorFactory interfaces to implement a custom
0422         // clone() method, which is necessary to avoid sharing between copies of the
0423         // function registry (and thus double-frees)
0424         // Not deeply immutable (the values in the function registry are mutable,
0425         // as a FormatterFactory can have mutable state
0426         const MFFunctionRegistry* customMFFunctionRegistry;
0427 
0428         // Data model, representing the parsed message
0429         MFDataModel dataModel;
0430 
0431         // Normalized version of the input string (optional whitespace removed)
0432         UnicodeString normalizedInput;
0433 
0434         // Errors -- only used while parsing and checking for data model errors; then
0435         // the MessageContext keeps track of errors
0436         // Must be a raw pointer to avoid including the internal header file
0437         // defining StaticErrors
0438         // Owned by `this`
0439         StaticErrors* errors = nullptr;
0440 
0441         // Error handling behavior.
0442         // If true, then formatting methods set their UErrorCode arguments
0443         // to signal MessageFormat errors, and no useful output is returned.
0444         // If false, then MessageFormat errors are not signaled and the
0445         // formatting methods return best-effort output.
0446         // The default is false.
0447         bool signalErrors = false;
0448     }; // class MessageFormatter
0449 
0450 } // namespace message2
0451 
0452 U_NAMESPACE_END
0453 
0454 #endif // U_HIDE_DEPRECATED_API
0455 
0456 #endif /* #if !UCONFIG_NO_MF2 */
0457 
0458 #endif /* #if !UCONFIG_NO_FORMATTING */
0459 
0460 #endif /* U_SHOW_CPLUSPLUS_API */
0461 
0462 #endif // MESSAGEFORMAT2_H
0463 
0464 // eof