// © 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_NORMALIZATION
#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 MessageFormatter;
class Parser;
class Serializer;
namespace data_model {
class Binding;
class Literal;
class Operator;
class MFDataModel;
/**
* 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;
};
/**
* 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_CLASS 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API const Literal& asLiteral() const;
/**
* Default constructor.
* Creates a null Operand.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API virtual Operand& operator=(Operand) noexcept;
/**
* Copy constructor.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
U_I18N_API Operand(const Operand&);
/**
* Destructor.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
U_I18N_API 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_CLASS 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.
*/
U_I18N_API 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.
*/
U_I18N_API const Literal& asLiteral() const;
/**
* Copy constructor.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API bool operator==(const Key& other) const;
/**
* Destructor.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
U_I18N_API virtual ~Key();
private:
/* const */ std::optional contents;
}; // class Key
/**
* 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_CLASS 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API 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.
*/
U_I18N_API SelectorKeys(const SelectorKeys& other);
/**
* Assignment operator.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
U_I18N_API SelectorKeys& operator=(SelectorKeys other) noexcept;
/**
* Destructor.
*
* @internal ICU 75 technology preview
* @deprecated This API is for technology preview only.
*/
U_I18N_API 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
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
// 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_CLASS OptionMap : public UObject {
public:
U_I18N_API int32_t size() const;
// Needs to take an error code b/c an earlier copy might have failed
U_I18N_API const Option& getOption(int32_t, UErrorCode&) const;
U_I18N_API 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);
}
U_I18N_API OptionMap() : len(0) {}
U_I18N_API OptionMap(const OptionMap&);
U_I18N_API OptionMap& operator=(OptionMap);
U_I18N_API std::vector