@@ -64,15 +64,10 @@ ResolvedFunctionOption::ResolvedFunctionOption(ResolvedFunctionOption&& other) {
6464}
6565
6666ResolvedFunctionOption::ResolvedFunctionOption (const UnicodeString& n,
67- FunctionValue* f) : name(n), value(f) {
68- U_ASSERT (f != nullptr );
69- }
67+ const FunctionValue& f) : name(n), value(&f) {}
7068
7169ResolvedFunctionOption::~ResolvedFunctionOption () {
72- if (value != nullptr ) {
73- delete value;
74- value = nullptr ;
75- }
70+ value = nullptr ; // value is not owned
7671}
7772
7873
@@ -98,7 +93,7 @@ FunctionOptions::getFunctionOption(const UnicodeString& key,
9893 for (int32_t i = 0 ; i < functionOptionsLen; i++) {
9994 const ResolvedFunctionOption& opt = options[i];
10095 if (opt.getName () == key) {
101- return opt.getValue ();
96+ return & opt.getValue ();
10297 }
10398 }
10499 status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -128,16 +123,22 @@ UnicodeString FunctionOptions::getStringFunctionOption(const UnicodeString& key)
128123 return result;
129124}
130125
131- FunctionOptions& FunctionOptions::operator =(FunctionOptions&& other) noexcept {
132- functionOptionsLen = other.functionOptionsLen ;
133- options = other.options ;
134- other.functionOptionsLen = 0 ;
135- other.options = nullptr ;
126+ FunctionOptions& FunctionOptions::operator =(FunctionOptions other) noexcept {
127+ swap (*this , other);
136128 return *this ;
137129}
138130
139- FunctionOptions::FunctionOptions (FunctionOptions&& other) {
140- *this = std::move (other);
131+ FunctionOptions::FunctionOptions (const FunctionOptions& other) {
132+ U_ASSERT (!other.bogus );
133+ functionOptionsLen = other.functionOptionsLen ;
134+ options = nullptr ;
135+ if (functionOptionsLen != 0 ) {
136+ UErrorCode localStatus = U_ZERO_ERROR;
137+ options = copyArray<ResolvedFunctionOption>(other.options , functionOptionsLen, localStatus);
138+ if (U_FAILURE (localStatus)) {
139+ bogus = true ;
140+ }
141+ }
141142}
142143
143144FunctionOptions::~FunctionOptions () {
@@ -158,36 +159,35 @@ static bool containsOption(const UVector& opts, const ResolvedFunctionOption& op
158159}
159160
160161// Options in `this` take precedence
161- // `this` can't be used after mergeOptions is called
162- FunctionOptions FunctionOptions::mergeOptions (FunctionOptions&& other,
163- UErrorCode& status) {
162+ FunctionOptions FunctionOptions::mergeOptions (const FunctionOptions& other,
163+ UErrorCode& status) const {
164164 UVector mergedOptions (status);
165165 mergedOptions.setDeleter (uprv_deleteUObject);
166166
167167 if (U_FAILURE (status)) {
168168 return {};
169169 }
170+ if (bogus || other.bogus ) {
171+ status = U_MEMORY_ALLOCATION_ERROR;
172+ return {};
173+ }
170174
171175 // Create a new vector consisting of the options from this `FunctionOptions`
172176 for (int32_t i = 0 ; i < functionOptionsLen; i++) {
173- mergedOptions.adoptElement (create<ResolvedFunctionOption>(std::move ( options[i]) , status),
177+ mergedOptions.adoptElement (create<ResolvedFunctionOption>(options[i], status),
174178 status);
175179 }
176180
177181 // Add each option from `other` that doesn't appear in this `FunctionOptions`
178182 for (int i = 0 ; i < other.functionOptionsLen ; i++) {
179183 // Note: this is quadratic in the length of `options`
180184 if (!containsOption (mergedOptions, other.options [i])) {
181- mergedOptions.adoptElement (create<ResolvedFunctionOption>(std::move ( other.options [i]) ,
182- status),
185+ mergedOptions.adoptElement (create<ResolvedFunctionOption>(other.options [i],
186+ status),
183187 status);
184188 }
185189 }
186190
187- delete[] options;
188- options = nullptr ;
189- functionOptionsLen = 0 ;
190-
191191 return FunctionOptions (std::move (mergedOptions), status);
192192}
193193
@@ -198,12 +198,8 @@ FunctionOptions FunctionOptions::mergeOptions(FunctionOptions&& other,
198198InternalValue::~InternalValue () {}
199199
200200InternalValue& InternalValue::operator =(InternalValue&& other) {
201- isFallbackValue = other.isFallbackValue ;
202201 fallbackString = other.fallbackString ;
203- if (!isFallbackValue) {
204- U_ASSERT (other.val .isValid ());
205- val.adoptInstead (other.val .orphan ());
206- }
202+ val = std::move (other.val );
207203 return *this ;
208204}
209205
@@ -214,48 +210,109 @@ InternalValue::InternalValue(InternalValue&& other) {
214210InternalValue::InternalValue (UErrorCode& errorCode) {
215211 CHECK_ERROR (errorCode);
216212
217- NullValue* nv = new NullValue ();
218- if (nv == nullptr ) {
213+ LocalPointer<FunctionValue> nv ( new NullValue () );
214+ if (!nv. isValid () ) {
219215 errorCode = U_MEMORY_ALLOCATION_ERROR;
220216 return ;
221217 }
222- val. adoptInstead (nv);
218+ val = std::move (nv);
223219}
224220
225221InternalValue::InternalValue (FunctionValue* v, const UnicodeString& fb)
226- : fallbackString(fb), val(v) {
222+ : fallbackString(fb) {
227223 U_ASSERT (v != nullptr );
224+ val = LocalPointer<FunctionValue>(v);
228225}
229226
230- FunctionValue* InternalValue::takeValue (UErrorCode& status) {
227+ const FunctionValue* InternalValue::getValue (UErrorCode& status) const {
231228 if (U_FAILURE (status)) {
232- return {} ;
229+ return nullptr ;
233230 }
234- if (isFallback ()) {
231+ // If this is a closure or fallback, error out
232+ if (!isEvaluated ()) {
235233 status = U_ILLEGAL_ARGUMENT_ERROR;
236- return {} ;
234+ return nullptr ;
237235 }
238- U_ASSERT (val.isValid ());
239- return val.orphan ();
236+ // Follow the indirection to get the value
237+ if (isIndirection ()) {
238+ const InternalValue* other = *std::get_if<const InternalValue*>(&val);
239+ U_ASSERT (other != nullptr );
240+ return other->getValue (status);
241+ }
242+ // Otherwise, return the contained FunctionValue
243+ const LocalPointer<FunctionValue>* result = std::get_if<LocalPointer<FunctionValue>>(&val);
244+ U_ASSERT (result->isValid ());
245+ return (*result).getAlias ();
240246}
241247
242- const FunctionValue* InternalValue::getValue (UErrorCode& status) const {
243- if (U_FAILURE (status)) {
244- return {};
248+ bool InternalValue::isSelectable () const {
249+ UErrorCode localStatus = U_ZERO_ERROR;
250+ const FunctionValue* val = getValue (localStatus);
251+ if (U_FAILURE (localStatus)) {
252+ return false ;
245253 }
246- if (isFallback ()) {
247- status = U_ILLEGAL_ARGUMENT_ERROR;
248- return {};
254+ return val->isSelectable ();
255+ }
256+
257+ /* static */ LocalPointer<InternalValue> InternalValue::null (UErrorCode& status) {
258+ if (U_SUCCESS (status)) {
259+ InternalValue* result = new InternalValue (status);
260+ if (U_SUCCESS (status)) {
261+ return LocalPointer<InternalValue>(result);
262+ }
249263 }
250- U_ASSERT (val.isValid ());
251- return val.getAlias ();
264+ return LocalPointer<InternalValue>();
252265}
253266
254- bool InternalValue::isSelectable () const {
255- if (isFallbackValue) {
267+ /* static */ LocalPointer<InternalValue> InternalValue::fallback (const UnicodeString& s,
268+ UErrorCode& status) {
269+ if (U_SUCCESS (status)) {
270+ InternalValue* result = new InternalValue (s);
271+ if (U_SUCCESS (status)) {
272+ return LocalPointer<InternalValue>(result);
273+ }
274+ }
275+ return LocalPointer<InternalValue>();
276+ }
277+
278+ /* static */ InternalValue InternalValue::closure (Closure* c, const UnicodeString& fb) {
279+ U_ASSERT (c != nullptr );
280+ return InternalValue (c, fb);
281+ }
282+
283+ bool InternalValue::isClosure () const {
284+ return std::holds_alternative<LocalPointer<Closure>>(val);
285+ }
286+
287+ bool InternalValue::isEvaluated () const {
288+ return std::holds_alternative<LocalPointer<FunctionValue>>(val) || isIndirection ();
289+ }
290+
291+ bool InternalValue::isIndirection () const {
292+ return std::holds_alternative<const InternalValue*>(val);
293+ }
294+
295+ bool InternalValue::isNullOperand () const {
296+ UErrorCode localStatus = U_ZERO_ERROR;
297+ const FunctionValue* val = getValue (localStatus);
298+ if (U_FAILURE (localStatus)) {
256299 return false ;
257300 }
258- return val->isSelectable ();
301+ return val->isNullOperand ();
302+ }
303+
304+ void InternalValue::update (InternalValue& newVal) {
305+ fallbackString = newVal.fallbackString ;
306+ val = &newVal;
307+ }
308+
309+ void InternalValue::update (LocalPointer<FunctionValue> newVal) {
310+ val = std::move (newVal);
311+ }
312+
313+ void InternalValue::update (const UnicodeString& fb) {
314+ fallbackString = fb;
315+ val = fb;
259316}
260317
261318// PrioritizedVariant
@@ -272,9 +329,11 @@ PrioritizedVariant::~PrioritizedVariant() {}
272329
273330 // ---------------- Environments and closures
274331
275- Environment* Environment::create (const VariableName& var, Closure&& c, Environment* parent, UErrorCode& errorCode) {
332+ Environment* Environment::create (const VariableName& var, Closure* c,
333+ const UnicodeString& fallbackStr,
334+ Environment* parent, UErrorCode& errorCode) {
276335 NULL_ON_ERROR (errorCode);
277- Environment* result = new NonEmptyEnvironment (var, std::move (c ), parent);
336+ Environment* result = new NonEmptyEnvironment (var, InternalValue::closure (c, fallbackStr ), parent);
278337 if (result == nullptr ) {
279338 errorCode = U_MEMORY_ALLOCATION_ERROR;
280339 return nullptr ;
@@ -284,21 +343,20 @@ PrioritizedVariant::~PrioritizedVariant() {}
284343
285344 Environment* Environment::create (UErrorCode& errorCode) {
286345 NULL_ON_ERROR (errorCode);
287- Environment* result = new EmptyEnvironment ();
288- if (result == nullptr ) {
346+ Environment* result = new EmptyEnvironment (errorCode );
347+ if (U_SUCCESS (errorCode) && result == nullptr ) {
289348 errorCode = U_MEMORY_ALLOCATION_ERROR;
290349 return nullptr ;
291350 }
292351 return result;
293352 }
294353
295- const Closure& EmptyEnvironment::lookup (const VariableName& v) const {
296- (void ) v;
354+ InternalValue& EmptyEnvironment::lookup (const VariableName&) {
297355 U_ASSERT (false );
298356 UPRV_UNREACHABLE_EXIT;
299357 }
300358
301- const Closure & NonEmptyEnvironment::lookup (const VariableName& v) const {
359+ InternalValue & NonEmptyEnvironment::lookup (const VariableName& v) {
302360 if (v == var) {
303361 return rhs;
304362 }
@@ -317,10 +375,75 @@ PrioritizedVariant::~PrioritizedVariant() {}
317375 return parent->has (v);
318376 }
319377
378+ InternalValue& EmptyEnvironment::createNull (UErrorCode& status) {
379+ if (U_FAILURE (status)) {
380+ return bogus ();
381+ }
382+ LocalPointer<InternalValue> val (InternalValue::null (status));
383+ return addUnnamedValue (std::move (val), status);
384+ }
385+
386+ InternalValue& EmptyEnvironment::createFallback (const UnicodeString& s, UErrorCode& status) {
387+ if (U_FAILURE (status)) {
388+ return bogus ();
389+ }
390+ LocalPointer<InternalValue> val (InternalValue::fallback (s, status));
391+ return addUnnamedValue (std::move (val), status);
392+ }
393+
394+ InternalValue& EmptyEnvironment::createUnnamed (InternalValue&& v, UErrorCode& status) {
395+ if (U_FAILURE (status)) {
396+ return bogus ();
397+ }
398+ LocalPointer<InternalValue> val (new InternalValue (std::move (v)));
399+ if (!val.isValid ()) {
400+ return bogus ();
401+ }
402+ return addUnnamedValue (std::move (val), status);
403+ }
404+
405+ InternalValue& NonEmptyEnvironment::createNull (UErrorCode& status) {
406+ return parent->createNull (status);
407+ }
408+
409+ InternalValue& NonEmptyEnvironment::createFallback (const UnicodeString& s, UErrorCode& status) {
410+ return parent->createFallback (s, status);
411+ }
412+
413+ InternalValue& NonEmptyEnvironment::createUnnamed (InternalValue&& v, UErrorCode& status) {
414+ return parent->createUnnamed (std::move (v), status);
415+ }
416+
417+ InternalValue& EmptyEnvironment::addUnnamedValue (LocalPointer<InternalValue> val,
418+ UErrorCode& status) {
419+ if (U_FAILURE (status)) {
420+ return bogus ();
421+ }
422+ U_ASSERT (val.isValid ());
423+ InternalValue* v = val.orphan ();
424+ unnamedValues.adoptElement (v, status);
425+ return *v;
426+ }
427+
428+ EmptyEnvironment::EmptyEnvironment (UErrorCode& status) : unnamedValues(UVector(status)) {
429+ unnamedValues.setDeleter (uprv_deleteUObject);
430+ }
431+
320432 Environment::~Environment () {}
321433 NonEmptyEnvironment::~NonEmptyEnvironment () {}
322434 EmptyEnvironment::~EmptyEnvironment () {}
323435
436+ /* static */ Closure* Closure::create (const Expression& expr, Environment& env,
437+ UErrorCode& status) {
438+ NULL_ON_ERROR (status);
439+
440+ Closure* result = new Closure (expr, env);
441+ if (result == nullptr ) {
442+ status = U_MEMORY_ALLOCATION_ERROR;
443+ }
444+ return result;
445+ }
446+
324447 Closure::~Closure () {}
325448
326449 // MessageContext methods
0 commit comments