From 8f24af4c28e74ef1769aef6ab00c480e09be7453 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Sun, 2 Mar 2014 23:28:10 +0100 Subject: work in progress to support implementing SPL interfaces, disabled the _self variable in Php::Base because by having each object keeping a reference to itself, the refcounter never reached zero and the object was thus never destructed, checking if we can get a new implementation one way or another --- include/base.h | 108 ++++++++++++++++++++------------------------------- include/class.h | 27 +++++++------ include/classbase.h | 32 ++++++++++++++- include/countable.h | 45 +++++++++++++++++++++ include/hashmember.h | 4 +- 5 files changed, 134 insertions(+), 82 deletions(-) create mode 100644 include/countable.h (limited to 'include') diff --git a/include/base.h b/include/base.h index 7d7be98..46f5678 100644 --- a/include/base.h +++ b/include/base.h @@ -22,6 +22,11 @@ protected: Base() {} public: + + // @todo should we delete the copy and move operators because we do not + // allow the CPP code to make copies of itself? + + /** * Virtual destructor */ @@ -31,122 +36,95 @@ public: * Convert the object to a Php::Value object (how it is used externally) * @return Object */ - Object &value() - { - return _self; - } +// Object value(); /** * Convert the object to a Php::Value object (how it is used externally) * @return Object */ - const Object &value() const - { - return _self; - } +// Object value() const; /** * Get access to a property by name using the [] operator * @param string - * @return Value + * @return HashMember */ - Value operator[](const char *name) - { - return _self[name]; - } +// HashMember operator[](const char *name) +// { +// return value()[name]; +// } /** * Alternative way to access a property using the [] operator * @param string - * @return Value + * @return HashMember */ - Value operator[](const std::string &name) - { - return _self[name]; - } +// HashMember operator[](const std::string &name) +// { +// return value()[name]; +// } /** * Retrieve a property by name * @param string - * @return Value + * @return HashMember */ - Value property(const char *name) - { - return _self[name]; - } +// HashMember property(const char *name) +// { +// return value()[name]; +// } /** * Retrieve a property by name * @param string - * @return Value + * @return HashMember */ - Value property(const std::string &name) - { - return _self[name]; - } +// HashMember property(const std::string &name) +// { +// return value()[name]; +// } /** * Get access to a property by name using the [] operator * @param string * @return Value */ - Value operator[](const char *name) const - { - return _self[name]; - } +// Value operator[](const char *name) const +// { +// return value()[name]; +// } /** * Alternative way to access a property using the [] operator * @param string * @return Value */ - Value operator[](const std::string &name) const - { - return _self[name]; - } +// Value operator[](const std::string &name) const +// { +// return value()[name]; +// } /** * Retrieve a property by name * @param string * @return Value */ - Value property(const char *name) const - { - return _self[name]; - } +// Value property(const char *name) const +// { +// return value()[name]; +// } /** * Retrieve a property by name * @param string * @return Value */ - Value property(const std::string &name) const - { - return _self[name]; - } +// Value property(const std::string &name) const +// { +// return value()[name]; +// } -protected: - /** - * The zend_object - * @var Value - */ - Object _self; - private: - /** - * Private method to assign the zend object - * @param zend_object - */ - void assign(Value &&object) - { - // copy pointer - _self = std::move(object); - } - - /** - * ClassBase has access to private data - */ - friend class ClassBase; }; diff --git a/include/class.h b/include/class.h index 851de8d..8bfcad4 100644 --- a/include/class.h +++ b/include/class.h @@ -15,11 +15,6 @@ * @copyright 2013, 2014 Copernica BV */ -/** - * Forward declarations - */ -struct _zend_class_entry; - /** * Set up namespace */ @@ -40,7 +35,11 @@ public: * * @param name Name of the class */ - Class(const char *name) : ClassBase(name) {} + Class(const char *name) : ClassBase(name) + { + // check for special classes + if (std::is_base_of::value) ClassBase::interface(Countable::implementation()); + } /** * Copy constructor @@ -74,14 +73,14 @@ public: * @param flags Optional flags * @param args Argument descriptions */ - void method(const char *name, void(T::*method)(), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } - void method(const char *name, void(T::*method)(Parameters ¶ms), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } - void method(const char *name, bool(T::*method)(), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } - void method(const char *name, bool(T::*method)(Parameters ¶ms), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } - void method(const char *name, void(T::*method)(), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } - void method(const char *name, void(T::*method)(Parameters ¶ms), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } - void method(const char *name, bool(T::*method)(), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } - void method(const char *name, bool(T::*method)(Parameters ¶ms), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } + void method(const char *name, void (T::*method)(), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } + void method(const char *name, void (T::*method)(Parameters ¶ms), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } + void method(const char *name, Value (T::*method)(), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } + void method(const char *name, Value (T::*method)(Parameters ¶ms), int flags, const Arguments &args = {}) { ClassBase::method(name, static_cast(method), flags, args); } + void method(const char *name, void (T::*method)(), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } + void method(const char *name, void (T::*method)(Parameters ¶ms), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } + void method(const char *name, Value (T::*method)(), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } + void method(const char *name, Value (T::*method)(Parameters ¶ms), const Arguments &args = {}) { ClassBase::method(name, static_cast(method), Public, args); } /** * Add an abstract method to the class diff --git a/include/classbase.h b/include/classbase.h index baa1624..e23c579 100644 --- a/include/classbase.h +++ b/include/classbase.h @@ -85,14 +85,15 @@ public: * @param value * @return Base */ - Base* construct(Value &&value) + Base* construct(const struct _zend_object_value &value) { // construct the base auto *result = construct(); if (!result) return nullptr; // assign the zend object to it - result->assign(std::move(value)); + // @todo fix this +// result->assign(value); // done return result; @@ -170,6 +171,27 @@ protected: void property(const char *name, const char *value, int flags = Php::Public); void property(const char *name, double value, int flags = Php::Public); + /** + * Add an implemented interface + * + * This can only be used to register interfaces that are already defined + * by Zend, and not for user space interface or custom extension interfaces. + * This is probably not so much of a problem, as this feature is mostly + * useful for interfaces like 'Countable', 'ArrayAccess', 'Iterator', et + * cetera. Interfaces defined in user space are in normal operations + * inaccessible (user space code normally runs after the extension has been + * set up) - so we do not need a feature to set these. + * + * It does however make sense to support implementing extension-specific + * interface. We may add this feature in the future. + * + * @param interface + */ + void interface(struct _zend_class_entry *interface) + { + // register the interface + _interfaces.push_back(interface); + } private: /** @@ -224,6 +246,12 @@ private: */ std::list> _members; + /** + * All interfaces that are implemented + * @var std::list + */ + std::list _interfaces; + }; /** diff --git a/include/countable.h b/include/countable.h new file mode 100644 index 0000000..12d87d5 --- /dev/null +++ b/include/countable.h @@ -0,0 +1,45 @@ +/** + * Countable.h + * + * "Interface" that can be "implemented" by your class. If you do, you + * create your class like this: + * + * class MyClass : public Php::Base, public Php::Countable { ... } + * + * You will have to implement the count() method, which should return the + * number of elements in the class + * + * @author Emiel Bruijntjes + * @copyright 2014 Copernica BV + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class Countable +{ +public: + /** + * Implementation of the countable interface + * @return zend_class_entry* + * @internal + */ + static struct _zend_class_entry *implementation(); + + /** + * Retrieve the number of items in the class + * @return Value + */ + virtual Value count() = 0; +}; + +/** + * End namespace + */ +} + diff --git a/include/hashmember.h b/include/hashmember.h index a61865c..9933445 100644 --- a/include/hashmember.h +++ b/include/hashmember.h @@ -350,6 +350,8 @@ private: */ HashMember(const Value *base, Type index) : _base(*base), _index(index) {} + // @todo add move constructor + /** * Protected copy constructor * @param value Other element @@ -389,7 +391,7 @@ private: * Only value objects may construct members */ friend class Value; - friend class Properties; + friend class Base; }; -- cgit v1.2.3