// © 2024 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING #if !UCONFIG_NO_MF2 #include "unicode/messageformat2_data_model.h" #include "messageformat2_allocation.h" #include "messageformat2_macros.h" #include "uvector.h" U_NAMESPACE_BEGIN namespace message2 { // Implementation //------------------ SelectorKeys const Key* SelectorKeys::getKeysInternal() const { return keys.getAlias(); } // Lexically order key lists bool SelectorKeys::operator<(const SelectorKeys& other) const { // Handle key lists of different sizes first -- // this case does have to be handled (even though it would // reflect a data model error) because of the need to produce // partial output if (len < other.len) { return true; } if (len > other.len) { return false; } for (int32_t i = 0; i < len; i++) { if (keys[i] < other.keys[i]) { return true; } if (!(keys[i] == other.keys[i])) { return false; } } // If we've reached here, all keys must be equal return false; } SelectorKeys::Builder::Builder(UErrorCode& status) { keys = createUVector(status); } SelectorKeys::Builder& SelectorKeys::Builder::add(Key&& key, UErrorCode& status) noexcept { U_ASSERT(keys != nullptr); if (U_SUCCESS(status)) { Key* k = create(std::move(key), status); keys->adoptElement(k, status); } return *this; } SelectorKeys SelectorKeys::Builder::build(UErrorCode& status) const { if (U_FAILURE(status)) { return {}; } U_ASSERT(keys != nullptr); return SelectorKeys(*keys, status); } SelectorKeys::Builder::~Builder() { if (keys != nullptr) { delete keys; } } SelectorKeys::SelectorKeys(const UVector& ks, UErrorCode& status) : len(ks.size()) { Key* result = copyVectorToArray(ks, status); if (U_FAILURE(status)) { return; } keys.adoptInstead(result); } SelectorKeys& SelectorKeys::operator=(SelectorKeys other) noexcept { swap(*this, other); return *this; } SelectorKeys::SelectorKeys(const SelectorKeys& other) : len(other.len) { UErrorCode localErrorCode = U_ZERO_ERROR; if (len != 0) { keys.adoptInstead(copyArray(other.keys.getAlias(), len, localErrorCode)); } if (U_FAILURE(localErrorCode)) { len = 0; } } SelectorKeys::~SelectorKeys() { len = 0; } //------------------ Literal bool Literal::operator<(const Literal& other) const { // Ignore quoting for the purposes of ordering return contents < other.contents; } bool Literal::operator==(const Literal& other) const { // Ignore quoting for the purposes of ordering return contents == other.contents; } UnicodeString Literal::quoted() const { UnicodeString result(PIPE); result += unquoted(); result += PIPE; return result; } const UnicodeString& Literal::unquoted() const { return contents; } Literal& Literal::operator=(Literal other) noexcept { swap(*this, other); return *this; } Literal::~Literal() { thisIsQuoted = false; } //------------------ Operand Operand::Operand(const Operand& other) : contents(other.contents) {} Operand& Operand::operator=(Operand other) noexcept { swap(*this, other); return *this; } UBool Operand::isVariable() const { return (contents.has_value() && std::holds_alternative(*contents)); } UBool Operand::isLiteral() const { return (contents.has_value() && std::holds_alternative(*contents)); } UBool Operand::isNull() const { return !contents.has_value(); } const Literal& Operand::asLiteral() const { U_ASSERT(isLiteral()); return *(std::get_if(&(*contents))); } const VariableName& Operand::asVariable() const { U_ASSERT(isVariable()); return *(std::get_if(&(*contents))); } Operand::~Operand() {} //---------------- Key Key& Key::operator=(Key other) noexcept { swap(*this, other); return *this; } bool Key::operator<(const Key& other) const { // Arbitrarily treat * as greater than all concrete keys if (isWildcard()) { return false; } if (other.isWildcard()) { return true; } return (asLiteral() < other.asLiteral()); } bool Key::operator==(const Key& other) const { if (isWildcard()) { return other.isWildcard(); } if (other.isWildcard()) { return false; } return (asLiteral() == other.asLiteral()); } const Literal& Key::asLiteral() const { U_ASSERT(!isWildcard()); return *contents; } Key::~Key() {} //------------------------ Operator OptionMap::OptionMap(const UVector& opts, UErrorCode& status) : len(opts.size()) { Option* result = copyVectorToArray