// © 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 "messageformat2_allocation.h" #include "messageformat2_evaluation.h" #include "messageformat2_macros.h" #include "uvector.h" // U_ASSERT U_NAMESPACE_BEGIN // Auxiliary data structures used during formatting a message namespace message2 { using namespace data_model; // Functions // ------------- ResolvedFunctionOption::ResolvedFunctionOption(ResolvedFunctionOption&& other) { name = std::move(other.name); value = std::move(other.value); } ResolvedFunctionOption::~ResolvedFunctionOption() {} const ResolvedFunctionOption* FunctionOptions::getResolvedFunctionOptions(int32_t& len) const { len = functionOptionsLen; U_ASSERT(len == 0 || options != nullptr); return options; } FunctionOptions::FunctionOptions(UVector&& optionsVector, UErrorCode& status) { CHECK_ERROR(status); functionOptionsLen = optionsVector.size(); options = moveVectorToArray(optionsVector, status); } UBool FunctionOptions::getFunctionOption(const UnicodeString& key, Formattable& option) const { if (options == nullptr) { U_ASSERT(functionOptionsLen == 0); } for (int32_t i = 0; i < functionOptionsLen; i++) { const ResolvedFunctionOption& opt = options[i]; if (opt.getName() == key) { option = opt.getValue(); return true; } } return false; } UnicodeString FunctionOptions::getStringFunctionOption(const UnicodeString& key) const { Formattable option; if (getFunctionOption(key, option)) { if (option.getType() == UFMT_STRING) { UErrorCode localErrorCode = U_ZERO_ERROR; UnicodeString val = option.getString(localErrorCode); U_ASSERT(U_SUCCESS(localErrorCode)); return val; } } // For anything else, including non-string values, return "". // Alternately, could try to stringify the non-string option. // (Currently, no tests require that.) return {}; } FunctionOptions& FunctionOptions::operator=(FunctionOptions&& other) noexcept { functionOptionsLen = other.functionOptionsLen; options = other.options; other.functionOptionsLen = 0; other.options = nullptr; return *this; } FunctionOptions::FunctionOptions(FunctionOptions&& other) { *this = std::move(other); } FunctionOptions::~FunctionOptions() { if (options != nullptr) { delete[] options; } } // ResolvedSelector // ---------------- ResolvedSelector::ResolvedSelector(const FunctionName& fn, Selector* sel, FunctionOptions&& opts, FormattedPlaceholder&& val) : selectorName(fn), selector(sel), options(std::move(opts)), value(std::move(val)) { U_ASSERT(sel != nullptr); } ResolvedSelector::ResolvedSelector(FormattedPlaceholder&& val) : value(std::move(val)) {} ResolvedSelector& ResolvedSelector::operator=(ResolvedSelector&& other) noexcept { selectorName = std::move(other.selectorName); selector.adoptInstead(other.selector.orphan()); options = std::move(other.options); value = std::move(other.value); return *this; } ResolvedSelector::ResolvedSelector(ResolvedSelector&& other) { *this = std::move(other); } ResolvedSelector::~ResolvedSelector() {} // PrioritizedVariant // ------------------ UBool PrioritizedVariant::operator<(const PrioritizedVariant& other) const { if (priority < other.priority) { return true; } return false; } PrioritizedVariant::~PrioritizedVariant() {} // ---------------- Environments and closures Environment* Environment::create(const VariableName& var, Closure&& c, Environment* parent, UErrorCode& errorCode) { NULL_ON_ERROR(errorCode); Environment* result = new NonEmptyEnvironment(var, std::move(c), parent); if (result == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return nullptr; } return result; } Environment* Environment::create(UErrorCode& errorCode) { NULL_ON_ERROR(errorCode); Environment* result = new EmptyEnvironment(); if (result == nullptr) { errorCode = U_MEMORY_ALLOCATION_ERROR; return nullptr; } return result; } const Closure& EmptyEnvironment::lookup(const VariableName& v) const { (void) v; U_ASSERT(false); UPRV_UNREACHABLE_EXIT; } const Closure& NonEmptyEnvironment::lookup(const VariableName& v) const { if (v == var) { return rhs; } return parent->lookup(v); } bool EmptyEnvironment::has(const VariableName& v) const { (void) v; return false; } bool NonEmptyEnvironment::has(const VariableName& v) const { if (v == var) { return true; } return parent->has(v); } Environment::~Environment() {} NonEmptyEnvironment::~NonEmptyEnvironment() {} EmptyEnvironment::~EmptyEnvironment() {} Closure::~Closure() {} // MessageContext methods void MessageContext::checkErrors(UErrorCode& status) const { CHECK_ERROR(status); errors.checkErrors(status); } const Formattable* MessageContext::getGlobal(const VariableName& v, UErrorCode& errorCode) const { return arguments.getArgument(v, errorCode); } MessageContext::MessageContext(const MessageArguments& args, const StaticErrors& e, UErrorCode& status) : arguments(args), errors(e, status) {} MessageContext::~MessageContext() {} } // namespace message2 U_NAMESPACE_END #endif /* #if !UCONFIG_NO_MF2 */ #endif /* #if !UCONFIG_NO_FORMATTING */