summaryrefslogtreecommitdiff
path: root/src/classimpl.h
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-02 22:25:45 +0200
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-02 22:25:45 +0200
commitbbdcdae98979e002476fc1e8296effd0b270928b (patch)
tree8634ff596c4209296a36dd7f8c54d00a8ec29478 /src/classimpl.h
parent735ec67aeb40e04a2cf47fa7216b2030c66b37fd (diff)
refactored the class and classbase classes, and introduced a classimpl class in the src directory, this is a first step to remove all zend-specific code from the header files, so that we can later have a hhvm backend for the php-cpp library
Diffstat (limited to 'src/classimpl.h')
-rw-r--r--src/classimpl.h407
1 files changed, 407 insertions, 0 deletions
diff --git a/src/classimpl.h b/src/classimpl.h
new file mode 100644
index 0000000..bfb4532
--- /dev/null
+++ b/src/classimpl.h
@@ -0,0 +1,407 @@
+/**
+ * ClassImpl.h
+ *
+ * Base implementation class that stores all methods and properties that
+ * exist for a class.
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Class definition
+ */
+class ClassImpl
+{
+private:
+ /**
+ * Pointer to the actual Php::Class<X> that is created in the extension
+ * @var ClassBase
+ */
+ ClassBase *_base = nullptr;
+
+ /**
+ * Name of the class
+ * @var string
+ */
+ std::string _name;
+
+ /**
+ * The comment for reflexion, with a stored pointer to ourselves
+ * @var char*
+ */
+ char *_comment = nullptr;
+
+ /**
+ * The class type (this can be values like Php::Abstract and Php::Final)
+ * @var ClassType
+ */
+ ClassType _type = ClassType::Regular;
+
+ /**
+ * The class entry
+ * @var zend_class_entry
+ */
+ zend_class_entry *_entry = nullptr;
+
+ /**
+ * Pointer to the entries
+ * @var zend_function_entry[]
+ */
+ zend_function_entry *_entries = nullptr;
+
+ /**
+ * All class methods
+ * @var std::list
+ */
+ std::list<std::shared_ptr<Method>> _methods;
+
+ /**
+ * All class members (class properties)
+ * @var std::list
+ */
+ std::list<std::shared_ptr<Member>> _members;
+
+ /**
+ * Map of dynamically accessible properties
+ * @var std::map
+ */
+ std::map<std::string,std::shared_ptr<Property>> _properties;
+
+
+ /**
+ * Retrieve an array of zend_function_entry objects that hold the
+ * properties for each method. This method is called at extension
+ * startup time to register all methods.
+ *
+ * @param classname The class name
+ * @return zend_function_entry[]
+ */
+ const zend_function_entry *entries();
+
+ /**
+ * Helper method to turn a property into a zval
+ * @param value
+ * @param type
+ * @return Value
+ */
+ static zval *toZval(Value &&value, int type);
+
+public:
+ /**
+ * Constructor
+ * @param name Class name
+ * @param type Class type
+ */
+ ClassImpl(const char *name, ClassType type) : _name(name), _type(type) {}
+
+ /**
+ * No copying or moving
+ * @param that
+ */
+ ClassImpl(const ClassImpl &that) = delete;
+ ClassImpl(ClassImpl &&that) = delete;
+
+ /**
+ * Destructor
+ */
+ virtual ~ClassImpl();
+
+ /**
+ * Retrieve the extension's class object
+ * @param entry
+ * @return ClassBase
+ */
+ static ClassBase *base(zend_class_entry *entry);
+
+ /**
+ * Initialize the class, given its name
+ *
+ * The module functions are registered on module startup, but classes are
+ * initialized afterwards. The Zend engine is a strange thing. Nevertheless,
+ * this means that this method is called after the module is already available.
+ * This function will inform the Zend engine about the existence of the
+ * class.
+ *
+ * @param base The extension C++ class
+ * @param ns Namespace name
+ * @param tsrm_ls
+ */
+ void initialize(ClassBase *base, const std::string &ns TSRMLS_DC);
+
+ /**
+ * Static member functions to create or clone objects based on this class
+ * @param entry Pointer to class information
+ * @param val The object to be cloned
+ * @param tsrm_ls
+ * @return zend_object_value Object info
+ */
+ static zend_object_value createObject(zend_class_entry *entry TSRMLS_DC);
+ static zend_object_value cloneObject(zval *val TSRMLS_DC);
+ static void destructObject(zend_object *object, unsigned int handle TSRMLS_DC);
+ static void freeObject(zend_object *object TSRMLS_DC);
+
+ /**
+ * Static member function that get called when a method or object is called
+ * @param ht ??
+ * @param return_value Zval holding the variable to store the return value in
+ * @param return_value_ptr Pointer to the same zval
+ * @param this_ptr Object being called
+ * @param return_value_used Is the return value used or not?
+ * @param tsrm_ls
+ */
+ static void callMethod(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC);
+ static void callInvoke(int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC);
+
+ /**
+ * Function that is used to count the number of elements in the object
+ * If the user has implemented the Countable interface, this method will
+ * call the count() method
+ * @param val
+ * @param count
+ * @param tsrm_ls
+ * @return int
+ */
+ static int countElements(zval *object, long *count TSRMLS_DC);
+
+ /**
+ * Function that is called when the object is used as an array in PHP
+ * @param object The object on which it is called
+ * @param offset The name of the property
+ * @param value The new value
+ * @param type The type of the variable???
+ * @param check_empty ????
+ * @return zval
+ */
+ static zval *readDimension(zval *object, zval *offset, int type TSRMLS_DC);
+ static void writeDimension(zval *object, zval *offset, zval *value TSRMLS_DC);
+ static int hasDimension(zval *object, zval *offset, int check_empty TSRMLS_DC);
+ static void unsetDimension(zval *object, zval *offset TSRMLS_DC);
+
+ /**
+ * Retrieve pointer to our own object handlers
+ * @return zend_object_handlers
+ */
+ zend_object_handlers *objectHandlers();
+
+ /**
+ * Function to create a new iterator to iterate over an object
+ * @param entry The class entry
+ * @param object The object to iterate over
+ * @param by_ref ?????
+ * @param tsrm_ls
+ * @return zend_object_iterator* Pointer to the iterator
+ */
+ static zend_object_iterator *getIterator(zend_class_entry *entry, zval *object, int by_ref TSRMLS_DC);
+
+ /**
+ * Function that is called when a property is being read
+ * @param object The object on which it is called
+ * @param offset The name of the property
+ * @param type The type of the variable???
+ * @param key ???
+ * @param tsrm_ls
+ * @return zval
+ */
+ static zval *readProperty(zval *object, zval *name, int type, const zend_literal *key TSRMLS_DC);
+ static zval *readProperty(zval *object, zval *name, int type TSRMLS_DC);
+
+ /**
+ * Function that is called when a property is set / updated
+ * @param object The object on which it is called
+ * @param name The name of the property
+ * @param value The new value
+ * @param key ???
+ * @param tsrm_ls
+ * @return zval
+ */
+ static void writeProperty(zval *object, zval *name, zval *value, const zend_literal *key TSRMLS_DC);
+ static void writeProperty(zval *object, zval *name, zval *value TSRMLS_DC);
+
+ /**
+ * Function that is called to check whether a certain property is set
+ * @param object The object on which it is called
+ * @param name The name of the property to check
+ * @param has_set_exists See above
+ * @param tsrm_ls
+ * @return bool
+ */
+ static int hasProperty(zval *object, zval *name, int has_set_exists, const zend_literal *key TSRMLS_DC);
+ static int hasProperty(zval *object, zval *name, int has_set_exists TSRMLS_DC);
+
+ /**
+ * Function that is called when a property is removed from the project
+ * @param object The object on which it is called
+ * @param member The member to remove
+ * @param tsrm_ls
+ */
+ static void unsetProperty(zval *object, zval *member, const zend_literal *key TSRMLS_DC);
+ static void unsetProperty(zval *object, zval *member TSRMLS_DC);
+
+ /**
+ * Method that returns information about the function signature of a undefined method
+ * @param object_ptr
+ * @param method
+ * @param method_len
+ * @param key
+ * @param tsrm_ls
+ * @return zend_function
+ */
+ static zend_function *getMethod(zval **object_ptr, char *method, int method_len TSRMLS_DC);
+ static zend_function *getMethod(zval **object_ptr, char *method, int method_len, const zend_literal *key TSRMLS_DC);
+
+ /**
+ * Method that returns information about the function signature of an undefined static method
+ * @param object_ptr
+ * @param method
+ * @param method_len
+ * @param key
+ * @param tsrm_ls
+ * @return zend_function
+ */
+ static zend_function *getStaticMethod(zend_class_entry *entry, char* method, int method_len TSRMLS_DC);
+
+ /**
+ * Method that returns information about the __invoke() method
+ * @param object
+ * @param entry
+ * @param func
+ * @param object_ptr
+ * @param tsrm_ls
+ * @return int
+ */
+ static int getClosure(zval *object, zend_class_entry **entry, zend_function **func, zval **object_ptr TSRMLS_DC);
+
+ /**
+ * Function to cast the object to a different type
+ * @param object
+ * @param retval
+ * @param type
+ * @param tsrm_ls
+ * @return int
+ */
+ static int cast(zval *object, zval *retval, int type TSRMLS_DC);
+
+ /**
+ * Function to compare two objects
+ * @param object1
+ * @param object2
+ * @param tsrm_ls
+ * @return int
+ */
+ static int compare(zval *object1, zval *object2 TSRMLS_DC);
+
+ /**
+ * Methods that are called to serialize/unserialize an object
+ * @param object The object to be serialized
+ * @param entry The class entry to which the object belongs
+ * @param buffer Buffer in which to store the data
+ * @param buf_len Size of the bufffer
+ * @param data Structure describing the serialize/unserialize data
+ * @param tsrm_ls
+ * @return int
+ */
+ static int serialize(zval *object, unsigned char **buffer, unsigned int *buf_len, zend_serialize_data *data TSRMLS_DC);
+ static int unserialize(zval **object, zend_class_entry *entry, const unsigned char *buffer, unsigned int buf_len, zend_unserialize_data *data TSRMLS_DC);
+
+ /**
+ * Add a method to the class
+ * zend_serialize_data
+ * The method will be accessible as one of the class methods in your PHP
+ * code. When the method is called, it will automatically be forwarded
+ * to the C++ implementation. The flags can be Php::Public, Php::Protected
+ * or Php::Private (using private methods can be useful if you for example
+ * want to make the __construct() function private). The access-modified
+ * flag can be bitwise combined with the flag Php::Final or Php::Abstract).
+ *
+ * @param name Name of the method
+ * @param method The actual method
+ * @param flags Optional flags
+ * @param args Description of the supported arguments
+ */
+ void method(const char *name, const method_callback_0 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+ void method(const char *name, const method_callback_1 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+ void method(const char *name, const method_callback_2 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+ void method(const char *name, const method_callback_3 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+ void method(const char *name, const method_callback_4 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+ void method(const char *name, const method_callback_5 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+ void method(const char *name, const method_callback_6 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+ void method(const char *name, const method_callback_7 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags, args)); }
+
+ /**
+ * Add a static method to the class
+ *
+ * Because a C++ static method is just a regular function, that happens to
+ * have access to the private variables of the class at compile time, you
+ * can register any function that matches one of the function signatures
+ *
+ * @param name Name of the method
+ * @param method The actual method
+ * @param flags Optional flags
+ * @param args Description of the supported arguments
+ */
+ void method(const char *name, const native_callback_0 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags | ZEND_ACC_STATIC, args)); }
+ void method(const char *name, const native_callback_1 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags | ZEND_ACC_STATIC, args)); }
+ void method(const char *name, const native_callback_2 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags | ZEND_ACC_STATIC, args)); }
+ void method(const char *name, const native_callback_3 &method, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, method, flags | ZEND_ACC_STATIC, args)); }
+
+ /**
+ * Add an abstract method to the class
+ *
+ * @param name Name of the method
+ * @param flags Optional flags (like public or protected)
+ * @param args Description of the supported arguments
+ */
+ void method(const char *name, int flags=0, const Arguments &args = {}) { _methods.push_back(std::make_shared<Method>(name, Abstract | flags, args)); }
+
+ /**
+ * Add a property to the class
+ *
+ * Every instance of this class will have this property. The property
+ * can be Php::Public, Php::Protected or Php::Private (altough setting
+ * private properties is odd as the implementation of the class is in CPP,
+ * so why use private properties while the whole implementation is already
+ * hidden)
+ *
+ * @param name Name of the property
+ * @param value Actual property value
+ * @param flags Optional flags
+ */
+ void property(const char *name, std::nullptr_t value, int flags = Php::Public) { _members.push_back(std::make_shared<NullMember>(name, flags)); }
+ void property(const char *name, int16_t value, int flags = Php::Public) { _members.push_back(std::make_shared<NumericMember>(name, value, flags)); }
+ void property(const char *name, int32_t value, int flags = Php::Public) { _members.push_back(std::make_shared<NumericMember>(name, value, flags)); }
+ void property(const char *name, int64_t value, int flags = Php::Public) { _members.push_back(std::make_shared<NumericMember>(name, value, flags)); }
+ void property(const char *name, bool value, int flags = Php::Public) { _members.push_back(std::make_shared<BoolMember>(name, value, flags)); }
+ void property(const char *name, char value, int flags = Php::Public) { _members.push_back(std::make_shared<StringMember>(name, &value, 1, flags)); }
+ void property(const char *name, const std::string &value, int flags = Php::Public) { _members.push_back(std::make_shared<StringMember>(name, value, flags)); }
+ void property(const char *name, const char *value, int flags = Php::Public) { _members.push_back(std::make_shared<StringMember>(name, value, strlen(value), flags)); }
+ void property(const char *name, double value, int flags = Php::Public) { _members.push_back(std::make_shared<FloatMember>(name, value, flags)); }
+
+ /**
+ * Set property with callbacks
+ * @param name Name of the property
+ * @param getter Getter method
+ * @param setter Setter method
+ */
+ void property(const char *name, const getter_callback_0 &getter) { _properties[name] = std::make_shared<Property>(getter); }
+ void property(const char *name, const getter_callback_1 &getter) { _properties[name] = std::make_shared<Property>(getter); }
+ void property(const char *name, const getter_callback_0 &getter, const setter_callback_0 &setter) { _properties[name] = std::make_shared<Property>(getter,setter); }
+ void property(const char *name, const getter_callback_1 &getter, const setter_callback_0 &setter) { _properties[name] = std::make_shared<Property>(getter,setter); }
+ void property(const char *name, const getter_callback_0 &getter, const setter_callback_1 &setter) { _properties[name] = std::make_shared<Property>(getter,setter); }
+ void property(const char *name, const getter_callback_1 &getter, const setter_callback_1 &setter) { _properties[name] = std::make_shared<Property>(getter,setter); }
+
+
+
+
+};
+
+/**
+ * End namespace
+ */
+}
+