diff options
Diffstat (limited to 'src/classimpl.cpp')
-rw-r--r-- | src/classimpl.cpp | 157 |
1 files changed, 65 insertions, 92 deletions
diff --git a/src/classimpl.cpp b/src/classimpl.cpp index ea7fdd7..84b43df 100644 --- a/src/classimpl.cpp +++ b/src/classimpl.cpp @@ -28,11 +28,15 @@ ClassImpl::~ClassImpl() } /** + * @todo refactor so that methods become simpler + */ + +/** * Retrieve our C++ implementation object * @param entry * @return ClassImpl */ -static ClassImpl *cpp_impl(zend_class_entry *entry) +static ClassImpl *self(zend_class_entry *entry) { // we need the base class (in user space the class may have been overridden, // but we are not interested in these user space classes) @@ -52,34 +56,6 @@ static ClassImpl *cpp_impl(zend_class_entry *entry) } /** - * Retrieve the extension's class object - * @param entry - * @return ClassBase - */ -ClassBase *ClassImpl::base(zend_class_entry *entry) -{ - // first the implementation class - ClassImpl *impl = cpp_impl(entry); - - // and now the base - return impl->_base; -} - -/** - * Retrieve the CPP object - * @param val - * @return Base - */ -static Base *cpp_object(const zval *val TSRMLS_DC) -{ - // retrieve the old object, which we are going to copy - MixedObject *object = (MixedObject *)zend_object_store_get_object(val TSRMLS_CC); - - // return the cpp object - return object->cpp; -} - -/** * Extended zend_internal_function structure that we use to store an * instance of the ClassBase object. We need this for static method calls */ @@ -244,7 +220,7 @@ zend_function *ClassImpl::getMethod(zval **object_ptr, char *method_name, int me function->function_name = method_name; // store pointer to ourselves - data->self = cpp_impl(entry); + data->self = self(entry); // done (cast to zend_function* is allowed, because a zend_function is a union // that has one member being a zend_internal_function) @@ -289,7 +265,7 @@ zend_function *ClassImpl::getStaticMethod(zend_class_entry *entry, char* method, function->function_name = method; // store pointer to ourselves - data->self = cpp_impl(entry); + data->self = self(entry); // done (cast to zend_function* is allowed, because a zend_function is a union // that has one member being a zend_internal_function) @@ -334,7 +310,7 @@ int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_funct function->function_name = nullptr; // store pointer to ourselves - data->self = cpp_impl(entry); + data->self = self(entry); // assign this dynamically allocated variable to the func parameter // the case is ok, because zend_internal_function is a member of the @@ -405,31 +381,31 @@ zend_object_handlers *ClassImpl::objectHandlers() /** * Function to compare two objects - * @param object1 - * @param object2 + * @param val1 + * @param val2 * @param tsrm_ls * @return int */ -int ClassImpl::compare(zval *object1, zval *object2 TSRMLS_DC) +int ClassImpl::compare(zval *val1, zval *val2 TSRMLS_DC) { // prevent exceptions try { // retrieve the class entry linked to this object - auto *entry = zend_get_class_entry(object1 TSRMLS_CC); + auto *entry = zend_get_class_entry(val1 TSRMLS_CC); // other object must be of the same type - if (entry != zend_get_class_entry(object2 TSRMLS_CC)) throw NotImplemented(); + if (entry != zend_get_class_entry(val2 TSRMLS_CC)) throw NotImplemented(); // we need the C++ class meta-information object - ClassBase *meta = base(entry); + ClassBase *meta = self(entry)->_base; // get the base objects - Base *base1 = cpp_object(object1 TSRMLS_CC); - Base *base2 = cpp_object(object2 TSRMLS_CC); + Base *object1 = ObjectImpl::find(val1 TSRMLS_CC)->object(); + Base *object2 = ObjectImpl::find(val2 TSRMLS_CC)->object(); // run the compare method - return meta->callCompare(base1, base2); + return meta->callCompare(object1, object2); } catch (const NotImplemented &exception) { @@ -437,7 +413,7 @@ int ClassImpl::compare(zval *object1, zval *object2 TSRMLS_DC) if (!std_object_handlers.compare_objects) return 1; // call default - return std_object_handlers.compare_objects(object1, object2 TSRMLS_CC); + return std_object_handlers.compare_objects(val1, val2 TSRMLS_CC); } catch (Exception &exception) { @@ -452,22 +428,22 @@ int ClassImpl::compare(zval *object1, zval *object2 TSRMLS_DC) /** * Function to cast the object to a different type - * @param object + * @param val * @param retval * @param type * @param tsrm_ls * @return int */ -int ClassImpl::cast(zval *object, zval *retval, int type TSRMLS_DC) +int ClassImpl::cast(zval *val, zval *retval, int type TSRMLS_DC) { - // get the base object - Base *base = cpp_object(object TSRMLS_CC); + // get the base c++ object + Base *object = ObjectImpl::find(val TSRMLS_CC)->object(); // retrieve the class entry linked to this object - auto *entry = zend_get_class_entry(object TSRMLS_CC); + auto *entry = zend_get_class_entry(val TSRMLS_CC); // we need the C++ class meta-information object - ClassBase *meta = ClassImpl::base(entry); + ClassBase *meta = self(entry)->_base; // retval it not yet initialized --- and again feelings of disbelief, // frustration, wonder and anger come up when you see that there are not two @@ -486,18 +462,18 @@ int ClassImpl::cast(zval *object, zval *retval, int type TSRMLS_DC) // check type switch ((Type)type) { - case Type::Numeric: result = meta->callToInteger(base).detach(); break; - case Type::Float: result = meta->callToFloat(base).detach(); break; - case Type::Bool: result = meta->callToBool(base).detach(); break; - case Type::String: result = meta->callToString(base).detach(); break; + case Type::Numeric: result = meta->callToInteger(object).detach(); break; + case Type::Float: result = meta->callToFloat(object).detach(); break; + case Type::Bool: result = meta->callToBool(object).detach(); break; + case Type::String: result = meta->callToString(object).detach(); break; default: throw NotImplemented(); break; } // @todo do we turn into endless conversion if the __toString object returns 'this' ?? // (and if it does: who cares? If the extension programmer is stupid, why do we have to suffer?) - // is the object overwritten? - if (object == retval) zval_dtor(object); + // is the original parameter overwritten? + if (val == retval) zval_dtor(val); // overwrite the result ZVAL_ZVAL(retval, result, 1, 1); @@ -511,7 +487,7 @@ int ClassImpl::cast(zval *object, zval *retval, int type TSRMLS_DC) if (!std_object_handlers.cast_object) return FAILURE; // call default - return std_object_handlers.cast_object(object, retval, type TSRMLS_CC); + return std_object_handlers.cast_object(val, retval, type TSRMLS_CC); } catch (Exception &exception) { @@ -534,14 +510,14 @@ zend_object_value ClassImpl::cloneObject(zval *val TSRMLS_DC) auto *entry = zend_get_class_entry(val TSRMLS_CC); // we need the C++ class meta-information object - ClassImpl *impl = cpp_impl(entry); + ClassImpl *impl = self(entry); ClassBase *meta = impl->_base; // retrieve the old object, which we are going to copy - MixedObject *old_object = (MixedObject *)zend_object_store_get_object(val TSRMLS_CC); + ObjectImpl *old_object = ObjectImpl::find(val TSRMLS_CC); // create a new base c++ object - auto *cpp = meta->clone(old_object->cpp); + auto *cpp = meta->clone(old_object->object()); // report error on failure (this does not occur because the cloneObject() // method is only installed as handler when we have seen that there is indeed @@ -555,14 +531,14 @@ zend_object_value ClassImpl::cloneObject(zval *val TSRMLS_DC) result.handlers = impl->objectHandlers(); // store the object - MixedObject *new_object = cpp->store(entry TSRMLS_CC); + ObjectImpl *new_object = new ObjectImpl(entry, cpp TSRMLS_CC); // store the object in the object cache - result.handle = cpp->handle(); + result.handle = new_object->handle(); // clone the members (this will also call the __clone() function if the user // had registered that as a visible method) - zend_objects_clone_members(&new_object->php, result, &old_object->php, Z_OBJ_HANDLE_P(val) TSRMLS_CC); + zend_objects_clone_members(new_object->php(), result, old_object->php(), Z_OBJ_HANDLE_P(val) TSRMLS_CC); // was a custom clone method installed? If not we call the magic c++ __clone method if (!entry->clone) meta->callClone(cpp); @@ -584,7 +560,7 @@ zend_object_value ClassImpl::cloneObject(zval *val TSRMLS_DC) int ClassImpl::countElements(zval *object, long *count TSRMLS_DC) { // does it implement the countable interface? - Countable *countable = dynamic_cast<Countable*>(cpp_object(object TSRMLS_CC)); + Countable *countable = dynamic_cast<Countable*>(ObjectImpl::find(object TSRMLS_CC)->object()); // if it does not implement the Countable interface, we rely on the default implementation if (countable) @@ -650,7 +626,7 @@ zval *ClassImpl::readDimension(zval *object, zval *offset, int type TSRMLS_DC) // does it implement the arrayaccess interface? - ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(cpp_object(object TSRMLS_CC)); + ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(ObjectImpl::find(object TSRMLS_CC)->object()); // if it does not implement the ArrayAccess interface, we rely on the default implementation if (arrayaccess) @@ -695,7 +671,7 @@ zval *ClassImpl::readDimension(zval *object, zval *offset, int type TSRMLS_DC) void ClassImpl::writeDimension(zval *object, zval *offset, zval *value TSRMLS_DC) { // does it implement the arrayaccess interface? - ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(cpp_object(object TSRMLS_CC)); + ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(ObjectImpl::find(object TSRMLS_CC)->object()); // if it does not implement the ArrayAccess interface, we rely on the default implementation if (arrayaccess) @@ -737,7 +713,7 @@ void ClassImpl::writeDimension(zval *object, zval *offset, zval *value TSRMLS_DC int ClassImpl::hasDimension(zval *object, zval *member, int check_empty TSRMLS_DC) { // does it implement the arrayaccess interface? - ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(cpp_object(object TSRMLS_CC)); + ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(ObjectImpl::find(object TSRMLS_CC)->object()); // if it does not implement the ArrayAccess interface, we rely on the default implementation if (arrayaccess) @@ -787,7 +763,7 @@ int ClassImpl::hasDimension(zval *object, zval *member, int check_empty TSRMLS_D void ClassImpl::unsetDimension(zval *object, zval *member TSRMLS_DC) { // does it implement the arrayaccess interface? - ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(cpp_object(object TSRMLS_CC)); + ArrayAccess *arrayaccess = dynamic_cast<ArrayAccess*>(ObjectImpl::find(object TSRMLS_CC)->object()); // if it does not implement the ArrayAccess interface, we rely on the default implementation if (arrayaccess) @@ -871,13 +847,13 @@ zval *ClassImpl::readProperty(zval *object, zval *name, int type, const zend_lit // that is in most cases simply impossible. // retrieve the object and class - Base *base = cpp_object(object TSRMLS_CC); + Base *base = ObjectImpl::find(object TSRMLS_CC)->object(); // retrieve the class entry linked to this object auto *entry = zend_get_class_entry(object TSRMLS_CC); // we need the C++ class meta-information object - ClassImpl *impl = cpp_impl(entry); + ClassImpl *impl = self(entry); ClassBase *meta = impl->_base; // the default implementation throws an exception, so by catching @@ -945,13 +921,13 @@ void ClassImpl::writeProperty(zval *object, zval *name, zval *value, const zend_ #endif { // retrieve the object and class - Base *base = cpp_object(object TSRMLS_CC); + Base *base = ObjectImpl::find(object TSRMLS_CC)->object(); // retrieve the class entry linked to this object auto *entry = zend_get_class_entry(object TSRMLS_CC); // we need the C++ class meta-information object - ClassImpl *impl = cpp_impl(entry); + ClassImpl *impl = self(entry); ClassBase *meta = impl->_base; // the default implementation throws an exception, if we catch that @@ -1030,13 +1006,13 @@ int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists, const z try { // get the cpp object - Base *base = cpp_object(object TSRMLS_CC); + Base *base = ObjectImpl::find(object TSRMLS_CC)->object(); // retrieve the class entry linked to this object auto *entry = zend_get_class_entry(object TSRMLS_CC); // we need the C++ class meta-information object - ClassImpl *impl = cpp_impl(entry); + ClassImpl *impl = self(entry); ClassBase *meta = impl->_base; // convert the name to a Value object @@ -1107,7 +1083,7 @@ void ClassImpl::unsetProperty(zval *object, zval *member, const zend_literal *ke auto *entry = zend_get_class_entry(object TSRMLS_CC); // we need the C++ class meta-information object - ClassImpl *impl = cpp_impl(entry); + ClassImpl *impl = self(entry); // property name Value name(member); @@ -1116,7 +1092,7 @@ void ClassImpl::unsetProperty(zval *object, zval *member, const zend_literal *ke auto iter = impl->_properties.find(name); // if the property does not exist, we forward to the __unset - if (iter == impl->_properties.end()) impl->_base->callUnset(cpp_object(object TSRMLS_CC), member); + if (iter == impl->_properties.end()) impl->_base->callUnset(ObjectImpl::find(object TSRMLS_CC)->object(), member); // callback properties cannot be unset zend_error(E_ERROR, "Property %s can not be unset", (const char *)name); @@ -1150,17 +1126,17 @@ void ClassImpl::unsetProperty(zval *object, zval *member, const zend_literal *ke */ void ClassImpl::destructObject(zend_object *object, zend_object_handle handle TSRMLS_DC) { - // allocate memory for the object - MixedObject *obj = (MixedObject *)object; + // find object + ObjectImpl *obj = ObjectImpl::find(object); // get meta info - ClassImpl *impl = cpp_impl(object->ce); + ClassImpl *impl = self(object->ce); // prevent exceptions try { // call the destruct function - if (obj->cpp) impl->_base->callDestruct(obj->cpp); + if (obj->object()) impl->_base->callDestruct(obj->object()); } catch (const NotImplemented &exception) { @@ -1183,13 +1159,10 @@ void ClassImpl::destructObject(zend_object *object, zend_object_handle handle TS void ClassImpl::freeObject(zend_object *object TSRMLS_DC) { // allocate memory for the object - MixedObject *obj = (MixedObject *)object; - - // deallocate the cpp object - if (obj->cpp) delete obj->cpp; + ObjectImpl *obj = ObjectImpl::find(object); - // pass on to the default destructor - zend_objects_free_object_storage(object TSRMLS_CC); + // no longer need it + obj->destruct(TSRMLS_CC); } /** @@ -1202,7 +1175,7 @@ void ClassImpl::freeObject(zend_object *object TSRMLS_DC) zend_object_value ClassImpl::createObject(zend_class_entry *entry TSRMLS_DC) { // we need the C++ class meta-information object - ClassImpl *impl = cpp_impl(entry); + ClassImpl *impl = self(entry); // create a new base C++ object auto *cpp = impl->_base->construct(); @@ -1216,11 +1189,11 @@ zend_object_value ClassImpl::createObject(zend_class_entry *entry TSRMLS_DC) // set the handlers result.handlers = impl->objectHandlers(); - // store the object - cpp->store(entry TSRMLS_CC); - + // create the object in the zend engine + ObjectImpl *object = new ObjectImpl(entry, cpp TSRMLS_CC); + // store the object in the object cache - result.handle = cpp->handle(); + result.handle = object->handle(); // done return result; @@ -1240,7 +1213,7 @@ zend_object_iterator *ClassImpl::getIterator(zend_class_entry *entry, zval *obje if (by_ref) throw Php::Exception("Foreach by ref is not possible"); // retrieve the traversable object - Traversable *traversable = dynamic_cast<Traversable*>(cpp_object(object TSRMLS_CC)); + Traversable *traversable = dynamic_cast<Traversable*>(ObjectImpl::find(object TSRMLS_CC)->object()); // user may throw an exception in the getIterator() function try @@ -1274,7 +1247,7 @@ zend_object_iterator *ClassImpl::getIterator(zend_class_entry *entry, zval *obje int ClassImpl::serialize(zval *object, unsigned char **buffer, zend_uint *buf_len, zend_serialize_data *data TSRMLS_DC) { // get the serializable object - Serializable *serializable = dynamic_cast<Serializable*>(cpp_object(object TSRMLS_CC)); + Serializable *serializable = dynamic_cast<Serializable*>(ObjectImpl::find(object TSRMLS_CC)->object()); // call the serialize method on the object auto value = serializable->serialize(); @@ -1304,7 +1277,7 @@ int ClassImpl::unserialize(zval **object, zend_class_entry *entry, const unsigne object_init_ex(*object, entry); // turn this into a serializale - Serializable *serializable = dynamic_cast<Serializable*>(cpp_object(*object TSRMLS_CC)); + Serializable *serializable = dynamic_cast<Serializable*>(ObjectImpl::find(*object TSRMLS_CC)->object()); // call the unserialize method on it serializable->unserialize((const char *)buffer, buf_len); |