xref: /aosp_15_r20/external/icu/icu4c/source/i18n/messageformat2_evaluation.cpp (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1 // © 2024 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 #include "unicode/utypes.h"
5 
6 #if !UCONFIG_NO_FORMATTING
7 
8 #if !UCONFIG_NO_MF2
9 
10 #include "messageformat2_allocation.h"
11 #include "messageformat2_evaluation.h"
12 #include "messageformat2_macros.h"
13 #include "uvector.h" // U_ASSERT
14 
15 U_NAMESPACE_BEGIN
16 
17 // Auxiliary data structures used during formatting a message
18 
19 namespace message2 {
20 
21 using namespace data_model;
22 
23 // Functions
24 // -------------
25 
ResolvedFunctionOption(ResolvedFunctionOption && other)26 ResolvedFunctionOption::ResolvedFunctionOption(ResolvedFunctionOption&& other) {
27     name = std::move(other.name);
28     value = std::move(other.value);
29 }
30 
~ResolvedFunctionOption()31 ResolvedFunctionOption::~ResolvedFunctionOption() {}
32 
33 
getResolvedFunctionOptions(int32_t & len) const34 const ResolvedFunctionOption* FunctionOptions::getResolvedFunctionOptions(int32_t& len) const {
35     len = functionOptionsLen;
36     U_ASSERT(len == 0 || options != nullptr);
37     return options;
38 }
39 
FunctionOptions(UVector && optionsVector,UErrorCode & status)40 FunctionOptions::FunctionOptions(UVector&& optionsVector, UErrorCode& status) {
41     CHECK_ERROR(status);
42 
43     functionOptionsLen = optionsVector.size();
44     options = moveVectorToArray<ResolvedFunctionOption>(optionsVector, status);
45 }
46 
getFunctionOption(const UnicodeString & key,Formattable & option) const47 UBool FunctionOptions::getFunctionOption(const UnicodeString& key, Formattable& option) const {
48     if (options == nullptr) {
49         U_ASSERT(functionOptionsLen == 0);
50     }
51     for (int32_t i = 0; i < functionOptionsLen; i++) {
52         const ResolvedFunctionOption& opt = options[i];
53         if (opt.getName() == key) {
54             option = opt.getValue();
55             return true;
56         }
57     }
58     return false;
59 }
60 
getStringFunctionOption(const UnicodeString & key) const61 UnicodeString FunctionOptions::getStringFunctionOption(const UnicodeString& key) const {
62     Formattable option;
63     if (getFunctionOption(key, option)) {
64         if (option.getType() == UFMT_STRING) {
65             UErrorCode localErrorCode = U_ZERO_ERROR;
66             UnicodeString val = option.getString(localErrorCode);
67             U_ASSERT(U_SUCCESS(localErrorCode));
68             return val;
69         }
70     }
71     // For anything else, including non-string values, return "".
72     // Alternately, could try to stringify the non-string option.
73     // (Currently, no tests require that.)
74     return {};
75 }
76 
operator =(FunctionOptions && other)77 FunctionOptions& FunctionOptions::operator=(FunctionOptions&& other) noexcept {
78     functionOptionsLen = other.functionOptionsLen;
79     options = other.options;
80     other.functionOptionsLen = 0;
81     other.options = nullptr;
82     return *this;
83 }
84 
FunctionOptions(FunctionOptions && other)85 FunctionOptions::FunctionOptions(FunctionOptions&& other) {
86     *this = std::move(other);
87 }
88 
~FunctionOptions()89 FunctionOptions::~FunctionOptions() {
90     if (options != nullptr) {
91         delete[] options;
92     }
93 }
94 // ResolvedSelector
95 // ----------------
96 
ResolvedSelector(const FunctionName & fn,Selector * sel,FunctionOptions && opts,FormattedPlaceholder && val)97 ResolvedSelector::ResolvedSelector(const FunctionName& fn,
98                                    Selector* sel,
99                                    FunctionOptions&& opts,
100                                    FormattedPlaceholder&& val)
101     : selectorName(fn), selector(sel), options(std::move(opts)), value(std::move(val))  {
102     U_ASSERT(sel != nullptr);
103 }
104 
ResolvedSelector(FormattedPlaceholder && val)105 ResolvedSelector::ResolvedSelector(FormattedPlaceholder&& val) : value(std::move(val)) {}
106 
operator =(ResolvedSelector && other)107 ResolvedSelector& ResolvedSelector::operator=(ResolvedSelector&& other) noexcept {
108     selectorName = std::move(other.selectorName);
109     selector.adoptInstead(other.selector.orphan());
110     options = std::move(other.options);
111     value = std::move(other.value);
112     return *this;
113 }
114 
ResolvedSelector(ResolvedSelector && other)115 ResolvedSelector::ResolvedSelector(ResolvedSelector&& other) {
116     *this = std::move(other);
117 }
118 
~ResolvedSelector()119 ResolvedSelector::~ResolvedSelector() {}
120 
121 // PrioritizedVariant
122 // ------------------
123 
operator <(const PrioritizedVariant & other) const124 UBool PrioritizedVariant::operator<(const PrioritizedVariant& other) const {
125   if (priority < other.priority) {
126       return true;
127   }
128   return false;
129 }
130 
~PrioritizedVariant()131 PrioritizedVariant::~PrioritizedVariant() {}
132 
133     // ---------------- Environments and closures
134 
create(const VariableName & var,Closure && c,Environment * parent,UErrorCode & errorCode)135     Environment* Environment::create(const VariableName& var, Closure&& c, Environment* parent, UErrorCode& errorCode) {
136         NULL_ON_ERROR(errorCode);
137         Environment* result = new NonEmptyEnvironment(var, std::move(c), parent);
138         if (result == nullptr) {
139             errorCode = U_MEMORY_ALLOCATION_ERROR;
140             return nullptr;
141         }
142         return result;
143     }
144 
create(UErrorCode & errorCode)145     Environment* Environment::create(UErrorCode& errorCode) {
146         NULL_ON_ERROR(errorCode);
147         Environment* result = new EmptyEnvironment();
148         if (result == nullptr) {
149             errorCode = U_MEMORY_ALLOCATION_ERROR;
150             return nullptr;
151         }
152         return result;
153     }
154 
lookup(const VariableName & v) const155     const Closure& EmptyEnvironment::lookup(const VariableName& v) const {
156         (void) v;
157         U_ASSERT(false);
158         UPRV_UNREACHABLE_EXIT;
159     }
160 
lookup(const VariableName & v) const161     const Closure& NonEmptyEnvironment::lookup(const VariableName& v) const {
162         if (v == var) {
163             return rhs;
164         }
165         return parent->lookup(v);
166     }
167 
has(const VariableName & v) const168     bool EmptyEnvironment::has(const VariableName& v) const {
169         (void) v;
170         return false;
171     }
172 
has(const VariableName & v) const173     bool NonEmptyEnvironment::has(const VariableName& v) const {
174         if (v == var) {
175             return true;
176         }
177         return parent->has(v);
178     }
179 
~Environment()180     Environment::~Environment() {}
~NonEmptyEnvironment()181     NonEmptyEnvironment::~NonEmptyEnvironment() {}
~EmptyEnvironment()182     EmptyEnvironment::~EmptyEnvironment() {}
183 
~Closure()184     Closure::~Closure() {}
185 
186     // MessageContext methods
187 
checkErrors(UErrorCode & status) const188     void MessageContext::checkErrors(UErrorCode& status) const {
189         CHECK_ERROR(status);
190         errors.checkErrors(status);
191     }
192 
getGlobal(const VariableName & v,UErrorCode & errorCode) const193     const Formattable* MessageContext::getGlobal(const VariableName& v, UErrorCode& errorCode) const {
194        return arguments.getArgument(v, errorCode);
195     }
196 
MessageContext(const MessageArguments & args,const StaticErrors & e,UErrorCode & status)197     MessageContext::MessageContext(const MessageArguments& args,
198                                    const StaticErrors& e,
199                                    UErrorCode& status) : arguments(args), errors(e, status) {}
~MessageContext()200     MessageContext::~MessageContext() {}
201 
202 } // namespace message2
203 U_NAMESPACE_END
204 
205 #endif /* #if !UCONFIG_NO_MF2 */
206 
207 #endif /* #if !UCONFIG_NO_FORMATTING */
208