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