summaryrefslogtreecommitdiff
path: root/zend/value.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zend/value.cpp')
-rw-r--r--zend/value.cpp61
1 files changed, 15 insertions, 46 deletions
diff --git a/zend/value.cpp b/zend/value.cpp
index d87e576..00fe969 100644
--- a/zend/value.cpp
+++ b/zend/value.cpp
@@ -315,59 +315,28 @@ Value &Value::operator=(Value &&value) _NOEXCEPT
// skip self assignment
if (this == &value) return *this;
- // is the object a reference?
- if (_val && Z_ISREF_P(_val))
+ // if neither value is a reference we can simply swap the values
+ // the other value will then destruct and reduce the refcount
+ if (!Z_ISREF_P(value._val) && (!_val || !Z_ISREF_P(_val)))
{
- // @todo difference if the other object is a reference or not?
-
- // the current object is a reference, this means that we should
- // keep the zval object, and copy the other value into it, get
- // the current refcount
- int refcount = Z_REFCOUNT_P(_val);
-
- // make the copy
- *_val = *value._val;
-
- // restore reference and refcount setting
- ZVAL_MAKE_REF(_val);
- Z_SET_REFCOUNT_P(_val, refcount);
-
- // how many references did the old variable have?
- if (Z_REFCOUNT_P(value._val) > 1)
- {
- // the other object already had multiple references, this
- // implies that many other PHP variables are also referring
- // to it, and we still need to store its contents, with one
- // reference less
- Z_DELREF_P(value._val);
-
- // and we need to run the copy constructor on the current
- // value, because we're making a deep copy
- zval_copy_ctor(_val);
- }
- else
- {
- // the last and only reference to the other object was
- // removed, we no longer need it
- delete value._val;
-
- // the other object is no longer valid
- value._val = nullptr;
- }
+ // just swap the pointer
+ std::swap(_val, value._val);
+ }
+ else if (_val)
+ {
+ // copy the value over to our local zval
+ ZVAL_COPY_VALUE(_val, value._val);
}
else
{
- // first destruct ourselves properly
- this->~Value();
+ // first swap the value out
+ std::swap(_val, value._val);
- // just copy the zval completely
- _val = value._val;
-
- // the other object is no longer valid
- value._val = nullptr;
+ // and make sure it is no longer a reference
+ ZVAL_UNREF(_val);
}
- // done
+ // allow chaining
return *this;
}