// © 2024 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html #include "unicode/utypes.h" #ifndef MESSAGEFORMAT_DATA_MODEL_H #define MESSAGEFORMAT_DATA_MODEL_H #if U_SHOW_CPLUSPLUS_API #if !UCONFIG_NO_FORMATTING #if !UCONFIG_NO_MF2 #include "unicode/localpointer.h" #include "unicode/messageformat2_data_model_names.h" #ifndef U_HIDE_DEPRECATED_API #include #include #include #include #include #include U_NAMESPACE_BEGIN class UVector; // Helpers // Note: this _must_ be declared `inline` or else gcc will generate code // for its instantiations, which needs to be avoided because it returns // a std::vector template static inline std::vector toStdVector(const T* arr, int32_t len) { std::vector result; for (int32_t i = 0; i < len; i++) { result.push_back(arr[i]); } return result; } #if defined(U_REAL_MSVC) #pragma warning(push) // Ignore warning 4251 as these templates are instantiated later in this file, // after the classes used to instantiate them have been defined. #pragma warning(disable: 4251) #endif namespace message2 { class Checker; class MFDataModel; class MessageFormatter; class Parser; class Serializer; namespace data_model { class Binding; class Literal; class Operator; /** * The `Literal` class corresponds to the `literal` nonterminal in the MessageFormat 2 grammar, * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf and the * `Literal` interface defined in * // https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions * * `Literal` is immutable, copyable and movable. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ class U_I18N_API Literal : public UObject { public: /** * Returns the quoted representation of this literal (enclosed in '|' characters) * * @return A string representation of the literal enclosed in quote characters. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ UnicodeString quoted() const; /** * Returns the parsed string contents of this literal. * * @return A string representation of this literal. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ const UnicodeString& unquoted() const; /** * Determines if this literal appeared as a quoted literal in the message. * * @return true if and only if this literal appeared as a quoted literal in the * message. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ UBool isQuoted() const { return thisIsQuoted; } /** * Literal constructor. * * @param q True if and only if this literal was parsed with the `quoted` nonterminal * (appeared enclosed in '|' characters in the message text). * @param s The string contents of this literal; escape sequences are assumed to have * been interpreted already. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Literal(UBool q, const UnicodeString& s) : thisIsQuoted(q), contents(s) {} /** * Copy constructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Literal(const Literal& other) : thisIsQuoted(other.thisIsQuoted), contents(other.contents) {} /** * Non-member swap function. * @param l1 will get l2's contents * @param l2 will get l1's contents * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ friend inline void swap(Literal& l1, Literal& l2) noexcept { using std::swap; swap(l1.thisIsQuoted, l2.thisIsQuoted); swap(l1.contents, l2.contents); } /** * Assignment operator. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Literal& operator=(Literal) noexcept; /** * Default constructor. * Puts the Literal into a valid but undefined state. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Literal() = default; /** * Less than operator. Compares `this.stringContents()` with * `other.stringContents()`. This method is used in representing * the mapping from key lists to patterns in a message with variants, * and is not expected to be useful otherwise. * * @param other The Literal to compare to this one. * @return true if the parsed string corresponding to this `Literal` * is less than the parsed string corresponding to the other `Literal` * (according to `UnicodeString`'s less-than operator). * Returns false otherwise. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ bool operator<(const Literal& other) const; /** * Equality operator. Compares `this.stringContents()` with * `other.stringContents()`. This method is used in representing * the mapping from key lists to patterns in a message with variants, * and is not expected to be useful otherwise. * * @param other The Literal to compare to this one. * @return true if the parsed string corresponding to this `Literal` * equals the parsed string corresponding to the other `Literal` * (according to `UnicodeString`'s equality operator). * Returns false otherwise. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ bool operator==(const Literal& other) const; /** * Destructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual ~Literal(); private: /* const */ bool thisIsQuoted = false; /* const */ UnicodeString contents; }; } // namespace data_model } // namespace message2 /// @cond DOXYGEN_IGNORE // Export an explicit template instantiation of the LocalPointer that is used as a // data member of various MFDataModel classes. // (When building DLLs for Windows this is required.) // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others // for similar examples.) #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN template class U_I18N_API LocalPointerBase; template class U_I18N_API LocalArray; #endif #if defined(U_REAL_MSVC) #pragma warning(pop) #endif /// @endcond U_NAMESPACE_END /// @cond DOXYGEN_IGNORE // Export an explicit template instantiation of the std::variants and std::optionals // that are used as a data member of various MFDataModel classes. // (When building DLLs for Windows this is required.) // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others // for similar examples.) #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN #if defined(U_REAL_MSVC) && defined(_MSVC_STL_VERSION) struct U_I18N_API std::_Nontrivial_dummy_type; template class U_I18N_API std::_Variant_storage_; #endif template class U_I18N_API std::variant; template class U_I18N_API std::optional>; template class U_I18N_API std::optional; #endif /// @endcond U_NAMESPACE_BEGIN namespace message2 { namespace data_model { /** * The `Operand` class corresponds to the `operand` nonterminal in the MessageFormat 2 grammar, * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf . * It represents a `Literal | VariableRef` -- see the `operand?` field of the `FunctionRef` * interface defined at: * https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#expressions * with the difference that it can also represent a null operand (the absent operand in an * `annotation` with no operand). * * `Operand` is immutable and is copyable and movable. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ class U_I18N_API Operand : public UObject { public: /** * Determines if this operand represents a variable. * * @return True if and only if the operand is a variable. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ UBool isVariable() const; /** * Determines if this operand represents a literal. * * @return True if and only if the operand is a literal. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ UBool isLiteral() const; /** * Determines if this operand is the null operand. * * @return True if and only if the operand is the null operand. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual UBool isNull() const; /** * Returns a reference to this operand's variable name. * Precondition: isVariable() * * @return A reference to the name of the variable * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ const UnicodeString& asVariable() const; /** * Returns a reference to this operand's literal contents. * Precondition: isLiteral() * * @return A reference to the literal * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ const Literal& asLiteral() const; /** * Default constructor. * Creates a null Operand. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Operand() : contents(std::nullopt) {} /** * Variable operand constructor. * * @param v The variable name; an operand corresponding * to a reference to `v` is returned. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ explicit Operand(const UnicodeString& v) : contents(VariableName(v)) {} /** * Literal operand constructor. * * @param l The literal to use for this operand; an operand * corresponding to `l` is returned. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ explicit Operand(const Literal& l) : contents(l) {} /** * Non-member swap function. * @param o1 will get o2's contents * @param o2 will get o1's contents * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ friend inline void swap(Operand& o1, Operand& o2) noexcept { using std::swap; (void) o1; (void) o2; swap(o1.contents, o2.contents); } /** * Assignment operator. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual Operand& operator=(Operand) noexcept; /** * Copy constructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Operand(const Operand&); /** * Destructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual ~Operand(); private: std::optional> contents; }; // class Operand /** * The `Key` class corresponds to the `key` nonterminal in the MessageFormat 2 grammar, * https://github.com/unicode-org/message-format-wg/blob/main/spec/message.abnf . * It also corresponds to * the `Literal | CatchallKey` that is the * element type of the `keys` array in the `Variant` interface * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages * * A key is either a literal or the wildcard symbol (represented in messages as '*') * * `Key` is immutable, copyable and movable. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ class U_I18N_API Key : public UObject { public: /** * Determines if this is a wildcard key * * @return True if and only if this is the wildcard key * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ UBool isWildcard() const { return !contents.has_value(); } /** * Returns the contents of this key as a literal. * Precondition: !isWildcard() * * @return The literal contents of the key * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ const Literal& asLiteral() const; /** * Copy constructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Key(const Key& other) : contents(other.contents) {} /** * Wildcard constructor; constructs a Key representing the * catchall or wildcard key, '*'. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Key() : contents(std::nullopt) {} /** * Literal key constructor. * * @param lit A Literal to use for this key. The result matches the * literal `lit`. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ explicit Key(const Literal& lit) : contents(lit) {} /** * Non-member swap function. * @param k1 will get k2's contents * @param k2 will get k1's contents * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ friend inline void swap(Key& k1, Key& k2) noexcept { using std::swap; swap(k1.contents, k2.contents); } /** * Assignment operator * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Key& operator=(Key) noexcept; /** * Less than operator. Compares the literal of `this` with the literal of `other`. * This method is used in representing the mapping from key lists to patterns * in a message with variants, and is not expected to be useful otherwise. * * @param other The Key to compare to this one. * @return true if the two `Key`s are not wildcards and if `this.asLiteral()` * < `other.asLiteral()`. * Returns false otherwise. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ bool operator<(const Key& other) const; /** * Equality operator. Compares the literal of `this` with the literal of `other`. * This method is used in representing the mapping from key lists to patterns * in a message with variants, and is not expected to be useful otherwise. * * @param other The Key to compare to this one. * @return true if either both `Key`s are wildcards, or `this.asLiteral()` * == `other.asLiteral()`. * Returns false otherwise. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ bool operator==(const Key& other) const; /** * Destructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual ~Key(); private: /* const */ std::optional contents; }; // class Key } // namespace data_model } // namespace message2 /// @cond DOXYGEN_IGNORE // Export an explicit template instantiation of the LocalPointer that is used as a // data member of various MFDataModel classes. // (When building DLLs for Windows this is required.) // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others // for similar examples.) #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN template class U_I18N_API LocalPointerBase; template class U_I18N_API LocalArray; #endif /// @endcond namespace message2 { namespace data_model { /** * The `SelectorKeys` class represents the key list for a single variant. * It corresponds to the `keys` array in the `Variant` interface * defined in https://github.com/unicode-org/message-format-wg/blob/main/spec/data-model.md#messages * * `SelectorKeys` is immutable, copyable and movable. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ class U_I18N_API SelectorKeys : public UObject { public: /** * Returns the underlying list of keys. * * @return The list of keys for this variant. * Returns an empty list if allocating this `SelectorKeys` * object previously failed. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ std::vector getKeys() const { return toStdVector(keys.getAlias(), len); } /** * The mutable `SelectorKeys::Builder` class allows the key list to be constructed * one key at a time. * * Builder is not copyable or movable. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ class U_I18N_API Builder : public UMemory { private: friend class SelectorKeys; UVector* keys; // This is a raw pointer and not a LocalPointer to avoid undefined behavior warnings, // since UVector is forward-declared // The vector owns its elements public: /** * Adds a single key to the list. * * @param key The key to be added. Passed by move * @param status Input/output error code * @return A reference to the builder. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Builder& add(Key&& key, UErrorCode& status) noexcept; /** * Constructs a new immutable `SelectorKeys` using the list of keys * set with previous `add()` calls. * * The builder object (`this`) can still be used after calling `build()`. * * @param status Input/output error code * @return The new SelectorKeys object * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ SelectorKeys build(UErrorCode& status) const; /** * Default constructor. * Returns a Builder with an empty list of keys. * * @param status Input/output error code * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Builder(UErrorCode& status); /** * Destructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual ~Builder(); Builder(const Builder&) = delete; Builder& operator=(const Builder&) = delete; Builder(Builder&&) = delete; Builder& operator=(Builder&&) = delete; }; // class SelectorKeys::Builder /** * Less than operator. Compares the two key lists lexicographically. * This method makes it possible for a `SelectorKeys` to be used as a map * key, which allows variants to be represented as a map. It is not expected * to be useful otherwise. * * @param other The SelectorKeys to compare to this one. * @return true if `this` is less than `other`, comparing the two key lists * lexicographically. * Returns false otherwise. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ bool operator<(const SelectorKeys& other) const; /** * Default constructor. * Puts the SelectorKeys into a valid but undefined state. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ SelectorKeys() : len(0) {} /** * Non-member swap function. * @param s1 will get s2's contents * @param s2 will get s1's contents * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ friend inline void swap(SelectorKeys& s1, SelectorKeys& s2) noexcept { using std::swap; swap(s1.len, s2.len); swap(s1.keys, s2.keys); } /** * Copy constructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ SelectorKeys(const SelectorKeys& other); /** * Assignment operator. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ SelectorKeys& operator=(SelectorKeys other) noexcept; /** * Destructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual ~SelectorKeys(); private: friend class Builder; friend class message2::Checker; friend class message2::MessageFormatter; friend class message2::Serializer; /* const */ LocalArray keys; /* const */ int32_t len; const Key* getKeysInternal() const; SelectorKeys(const UVector& ks, UErrorCode& status); }; // class SelectorKeys } // namespace data_model namespace data_model { class Operator; /** * An `Option` pairs an option name with an Operand. * * `Option` is immutable, copyable and movable. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ class U_I18N_API Option : public UObject { public: /** * Accesses the right-hand side of the option. * * @return A reference to the operand. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ const Operand& getValue() const { return rand; } /** * Accesses the left-hand side of the option. * * @return A reference to the option name. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ const UnicodeString& getName() const { return name; } /** * Constructor. Returns an `Option` representing the * named option "name=rand". * * @param n The name of the option. * @param r The value of the option. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Option(const UnicodeString& n, Operand&& r) : name(n), rand(std::move(r)) {} /** * Default constructor. * Returns an Option in a valid but undefined state. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Option() {} /** * Non-member swap function. * @param o1 will get o2's contents * @param o2 will get o1's contents * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ friend inline void swap(Option& o1, Option& o2) noexcept { using std::swap; swap(o1.name, o2.name); swap(o1.rand, o2.rand); } /** * Copy constructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Option(const Option& other); /** * Assignment operator * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ Option& operator=(Option other) noexcept; /** * Destructor. * * @internal ICU 75 technology preview * @deprecated This API is for technology preview only. */ virtual ~Option(); private: /* const */ UnicodeString name; /* const */ Operand rand; }; // class Option } // namespace data_model } // namespace message2 /// @cond DOXYGEN_IGNORE // Export an explicit template instantiation of the LocalPointer that is used as a // data member of various MFDataModel classes. // (When building DLLs for Windows this is required.) // (See measunit_impl.h, datefmt.h, collationiterator.h, erarules.h and others // for similar examples.) #if U_PF_WINDOWS <= U_PLATFORM && U_PLATFORM <= U_PF_CYGWIN template class U_I18N_API LocalPointerBase; template class U_I18N_API LocalArray; #endif /// @endcond namespace message2 { namespace data_model { // Internal only #ifndef U_IN_DOXYGEN // Options // This is a wrapper class around a vector of options that provides lookup operations class U_I18N_API OptionMap : public UObject { public: int32_t size() const; // Needs to take an error code b/c an earlier copy might have failed const Option& getOption(int32_t, UErrorCode&) const; friend inline void swap(OptionMap& m1, OptionMap& m2) noexcept { using std::swap; swap(m1.bogus, m2.bogus); swap(m1.options, m2.options); swap(m1.len, m2.len); } OptionMap() : len(0) {} OptionMap(const OptionMap&); OptionMap& operator=(OptionMap); std::vector