@@ -66,15 +66,10 @@ ResolvedFunctionOption::ResolvedFunctionOption(ResolvedFunctionOption&& other) {
6666}
6767
6868ResolvedFunctionOption::ResolvedFunctionOption (const UnicodeString& n,
69- FunctionValue* f) : name(n), value(f) {
70- U_ASSERT (f != nullptr );
71- }
69+ const FunctionValue& f) : name(n), value(&f) {}
7270
7371ResolvedFunctionOption::~ResolvedFunctionOption () {
74- if (value != nullptr ) {
75- delete value;
76- value = nullptr ;
77- }
72+ value = nullptr ; // value is not owned
7873}
7974
8075
@@ -100,7 +95,7 @@ FunctionOptions::getFunctionOption(const UnicodeString& key,
10095 for (int32_t i = 0 ; i < functionOptionsLen; i++) {
10196 const ResolvedFunctionOption& opt = options[i];
10297 if (opt.getName () == key) {
103- return opt.getValue ();
98+ return & opt.getValue ();
10499 }
105100 }
106101 status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -130,16 +125,22 @@ UnicodeString FunctionOptions::getStringFunctionOption(const UnicodeString& key)
130125 return result;
131126}
132127
133- FunctionOptions& FunctionOptions::operator =(FunctionOptions&& other) noexcept {
134- functionOptionsLen = other.functionOptionsLen ;
135- options = other.options ;
136- other.functionOptionsLen = 0 ;
137- other.options = nullptr ;
128+ FunctionOptions& FunctionOptions::operator =(FunctionOptions other) noexcept {
129+ swap (*this , other);
138130 return *this ;
139131}
140132
141- FunctionOptions::FunctionOptions (FunctionOptions&& other) {
142- *this = std::move (other);
133+ FunctionOptions::FunctionOptions (const FunctionOptions& other) {
134+ U_ASSERT (!other.bogus );
135+ functionOptionsLen = other.functionOptionsLen ;
136+ options = nullptr ;
137+ if (functionOptionsLen != 0 ) {
138+ UErrorCode localStatus = U_ZERO_ERROR;
139+ options = copyArray<ResolvedFunctionOption>(other.options , functionOptionsLen, localStatus);
140+ if (U_FAILURE (localStatus)) {
141+ bogus = true ;
142+ }
143+ }
143144}
144145
145146FunctionOptions::~FunctionOptions () {
@@ -160,36 +161,35 @@ static bool containsOption(const UVector& opts, const ResolvedFunctionOption& op
160161}
161162
162163// Options in `this` take precedence
163- // `this` can't be used after mergeOptions is called
164- FunctionOptions FunctionOptions::mergeOptions (FunctionOptions&& other,
165- UErrorCode& status) {
164+ FunctionOptions FunctionOptions::mergeOptions (const FunctionOptions& other,
165+ UErrorCode& status) const {
166166 UVector mergedOptions (status);
167167 mergedOptions.setDeleter (uprv_deleteUObject);
168168
169169 if (U_FAILURE (status)) {
170170 return {};
171171 }
172+ if (bogus || other.bogus ) {
173+ status = U_MEMORY_ALLOCATION_ERROR;
174+ return {};
175+ }
172176
173177 // Create a new vector consisting of the options from this `FunctionOptions`
174178 for (int32_t i = 0 ; i < functionOptionsLen; i++) {
175- mergedOptions.adoptElement (create<ResolvedFunctionOption>(std::move ( options[i]) , status),
179+ mergedOptions.adoptElement (create<ResolvedFunctionOption>(options[i], status),
176180 status);
177181 }
178182
179183 // Add each option from `other` that doesn't appear in this `FunctionOptions`
180184 for (int i = 0 ; i < other.functionOptionsLen ; i++) {
181185 // Note: this is quadratic in the length of `options`
182186 if (!containsOption (mergedOptions, other.options [i])) {
183- mergedOptions.adoptElement (create<ResolvedFunctionOption>(std::move ( other.options [i]) ,
184- status),
187+ mergedOptions.adoptElement (create<ResolvedFunctionOption>(other.options [i],
188+ status),
185189 status);
186190 }
187191 }
188192
189- delete[] options;
190- options = nullptr ;
191- functionOptionsLen = 0 ;
192-
193193 return FunctionOptions (std::move (mergedOptions), status);
194194}
195195
@@ -200,12 +200,8 @@ FunctionOptions FunctionOptions::mergeOptions(FunctionOptions&& other,
200200InternalValue::~InternalValue () {}
201201
202202InternalValue& InternalValue::operator =(InternalValue&& other) {
203- isFallbackValue = other.isFallbackValue ;
204203 fallbackString = other.fallbackString ;
205- if (!isFallbackValue) {
206- U_ASSERT (other.val .isValid ());
207- val.adoptInstead (other.val .orphan ());
208- }
204+ val = std::move (other.val );
209205 return *this ;
210206}
211207
@@ -216,48 +212,109 @@ InternalValue::InternalValue(InternalValue&& other) {
216212InternalValue::InternalValue (UErrorCode& errorCode) {
217213 CHECK_ERROR (errorCode);
218214
219- NullValue* nv = new NullValue ();
220- if (nv == nullptr ) {
215+ LocalPointer<FunctionValue> nv ( new NullValue () );
216+ if (!nv. isValid () ) {
221217 errorCode = U_MEMORY_ALLOCATION_ERROR;
222218 return ;
223219 }
224- val. adoptInstead (nv);
220+ val = std::move (nv);
225221}
226222
227223InternalValue::InternalValue (FunctionValue* v, const UnicodeString& fb)
228- : fallbackString(fb), val(v) {
224+ : fallbackString(fb) {
229225 U_ASSERT (v != nullptr );
226+ val = LocalPointer<FunctionValue>(v);
230227}
231228
232- FunctionValue* InternalValue::takeValue (UErrorCode& status) {
229+ const FunctionValue* InternalValue::getValue (UErrorCode& status) const {
233230 if (U_FAILURE (status)) {
234- return {} ;
231+ return nullptr ;
235232 }
236- if (isFallback ()) {
233+ // If this is a closure or fallback, error out
234+ if (!isEvaluated ()) {
237235 status = U_ILLEGAL_ARGUMENT_ERROR;
238- return {};
236+ return nullptr ;
237+ }
238+ // Follow the indirection to get the value
239+ if (isIndirection ()) {
240+ const InternalValue* other = *std::get_if<const InternalValue*>(&val);
241+ U_ASSERT (other != nullptr );
242+ return other->getValue (status);
243+ }
244+ // Otherwise, return the contained FunctionValue
245+ const LocalPointer<FunctionValue>* result = std::get_if<LocalPointer<FunctionValue>>(&val);
246+ U_ASSERT (result->isValid ());
247+ return (*result).getAlias ();
248+ }
249+
250+ bool InternalValue::isSelectable () const {
251+ UErrorCode localStatus = U_ZERO_ERROR;
252+ const FunctionValue* val = getValue (localStatus);
253+ if (U_FAILURE (localStatus)) {
254+ return false ;
239255 }
240- U_ASSERT (val.isValid ());
241- return val.orphan ();
256+ return val->isSelectable ();
242257}
243258
244- const FunctionValue* InternalValue::getValue (UErrorCode& status) const {
245- if (U_FAILURE (status)) {
246- return {};
259+ /* static */ LocalPointer<InternalValue> InternalValue::null (UErrorCode& status) {
260+ if (U_SUCCESS (status)) {
261+ InternalValue* result = new InternalValue (status);
262+ if (U_SUCCESS (status)) {
263+ return LocalPointer<InternalValue>(result);
264+ }
247265 }
248- if (isFallback ()) {
249- status = U_ILLEGAL_ARGUMENT_ERROR;
250- return {};
266+ return LocalPointer<InternalValue>();
267+ }
268+
269+ /* static */ LocalPointer<InternalValue> InternalValue::fallback (const UnicodeString& s,
270+ UErrorCode& status) {
271+ if (U_SUCCESS (status)) {
272+ InternalValue* result = new InternalValue (s);
273+ if (U_SUCCESS (status)) {
274+ return LocalPointer<InternalValue>(result);
275+ }
251276 }
252- U_ASSERT (val.isValid ());
253- return val.getAlias ();
277+ return LocalPointer<InternalValue>();
254278}
255279
256- bool InternalValue::isSelectable () const {
257- if (isFallbackValue) {
280+ /* static */ InternalValue InternalValue::closure (Closure* c, const UnicodeString& fb) {
281+ U_ASSERT (c != nullptr );
282+ return InternalValue (c, fb);
283+ }
284+
285+ bool InternalValue::isClosure () const {
286+ return std::holds_alternative<LocalPointer<Closure>>(val);
287+ }
288+
289+ bool InternalValue::isEvaluated () const {
290+ return std::holds_alternative<LocalPointer<FunctionValue>>(val) || isIndirection ();
291+ }
292+
293+ bool InternalValue::isIndirection () const {
294+ return std::holds_alternative<const InternalValue*>(val);
295+ }
296+
297+ bool InternalValue::isNullOperand () const {
298+ UErrorCode localStatus = U_ZERO_ERROR;
299+ const FunctionValue* val = getValue (localStatus);
300+ if (U_FAILURE (localStatus)) {
258301 return false ;
259302 }
260- return val->isSelectable ();
303+ return val->isNullOperand ();
304+ }
305+
306+ void InternalValue::update (InternalValue& newVal) {
307+ fallbackString = newVal.fallbackString ;
308+ val = &newVal;
309+ }
310+
311+ void InternalValue::update (LocalPointer<FunctionValue> newVal) {
312+ val = std::move (newVal);
313+ }
314+
315+ void InternalValue::update (const UnicodeString& fb) {
316+ fallbackString = fb;
317+ val = fb;
261318}
262319
263320// PrioritizedVariant
@@ -274,9 +331,11 @@ PrioritizedVariant::~PrioritizedVariant() {}
274331
275332 // ---------------- Environments and closures
276333
277- Environment* Environment::create (const VariableName& var, Closure&& c, Environment* parent, UErrorCode& errorCode) {
334+ Environment* Environment::create (const VariableName& var, Closure* c,
335+ const UnicodeString& fallbackStr,
336+ Environment* parent, UErrorCode& errorCode) {
278337 NULL_ON_ERROR (errorCode);
279- Environment* result = new NonEmptyEnvironment (var, std::move (c ), parent);
338+ Environment* result = new NonEmptyEnvironment (var, InternalValue::closure (c, fallbackStr ), parent);
280339 if (result == nullptr ) {
281340 errorCode = U_MEMORY_ALLOCATION_ERROR;
282341 return nullptr ;
@@ -286,21 +345,20 @@ PrioritizedVariant::~PrioritizedVariant() {}
286345
287346 Environment* Environment::create (UErrorCode& errorCode) {
288347 NULL_ON_ERROR (errorCode);
289- Environment* result = new EmptyEnvironment ();
290- if (result == nullptr ) {
348+ Environment* result = new EmptyEnvironment (errorCode );
349+ if (U_SUCCESS (errorCode) && result == nullptr ) {
291350 errorCode = U_MEMORY_ALLOCATION_ERROR;
292351 return nullptr ;
293352 }
294353 return result;
295354 }
296355
297- const Closure& EmptyEnvironment::lookup (const VariableName& v) const {
298- (void ) v;
356+ InternalValue& EmptyEnvironment::lookup (const VariableName&) {
299357 U_ASSERT (false );
300358 UPRV_UNREACHABLE_EXIT;
301359 }
302360
303- const Closure & NonEmptyEnvironment::lookup (const VariableName& v) const {
361+ InternalValue & NonEmptyEnvironment::lookup (const VariableName& v) {
304362 if (v == var) {
305363 return rhs;
306364 }
@@ -319,10 +377,75 @@ PrioritizedVariant::~PrioritizedVariant() {}
319377 return parent->has (v);
320378 }
321379
380+ InternalValue& EmptyEnvironment::createNull (UErrorCode& status) {
381+ if (U_FAILURE (status)) {
382+ return bogus ();
383+ }
384+ LocalPointer<InternalValue> val (InternalValue::null (status));
385+ return addUnnamedValue (std::move (val), status);
386+ }
387+
388+ InternalValue& EmptyEnvironment::createFallback (const UnicodeString& s, UErrorCode& status) {
389+ if (U_FAILURE (status)) {
390+ return bogus ();
391+ }
392+ LocalPointer<InternalValue> val (InternalValue::fallback (s, status));
393+ return addUnnamedValue (std::move (val), status);
394+ }
395+
396+ InternalValue& EmptyEnvironment::createUnnamed (InternalValue&& v, UErrorCode& status) {
397+ if (U_FAILURE (status)) {
398+ return bogus ();
399+ }
400+ LocalPointer<InternalValue> val (new InternalValue (std::move (v)));
401+ if (!val.isValid ()) {
402+ return bogus ();
403+ }
404+ return addUnnamedValue (std::move (val), status);
405+ }
406+
407+ InternalValue& NonEmptyEnvironment::createNull (UErrorCode& status) {
408+ return parent->createNull (status);
409+ }
410+
411+ InternalValue& NonEmptyEnvironment::createFallback (const UnicodeString& s, UErrorCode& status) {
412+ return parent->createFallback (s, status);
413+ }
414+
415+ InternalValue& NonEmptyEnvironment::createUnnamed (InternalValue&& v, UErrorCode& status) {
416+ return parent->createUnnamed (std::move (v), status);
417+ }
418+
419+ InternalValue& EmptyEnvironment::addUnnamedValue (LocalPointer<InternalValue> val,
420+ UErrorCode& status) {
421+ if (U_FAILURE (status)) {
422+ return bogus ();
423+ }
424+ U_ASSERT (val.isValid ());
425+ InternalValue* v = val.orphan ();
426+ unnamedValues.adoptElement (v, status);
427+ return *v;
428+ }
429+
430+ EmptyEnvironment::EmptyEnvironment (UErrorCode& status) : unnamedValues(UVector(status)) {
431+ unnamedValues.setDeleter (uprv_deleteUObject);
432+ }
433+
322434 Environment::~Environment () {}
323435 NonEmptyEnvironment::~NonEmptyEnvironment () {}
324436 EmptyEnvironment::~EmptyEnvironment () {}
325437
438+ /* static */ Closure* Closure::create (const Expression& expr, Environment& env,
439+ UErrorCode& status) {
440+ NULL_ON_ERROR (status);
441+
442+ Closure* result = new Closure (expr, env);
443+ if (result == nullptr ) {
444+ status = U_MEMORY_ALLOCATION_ERROR;
445+ }
446+ return result;
447+ }
448+
326449 Closure::~Closure () {}
327450
328451 // MessageContext methods
0 commit comments