summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-06 21:53:24 +0200
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-04-06 21:53:24 +0200
commit35fd3ccbeb4def71b4d8a59dfbb5c31201b099b9 (patch)
tree915223360aed4743aa6127fde4836aa413a260e5 /src
parentda4710512865e6816585ac4ab8edab2fa125e2d8 (diff)
renamed src directory to zend directory, disabled TSRM debug code
Diffstat (limited to 'src')
-rw-r--r--src/arithmetic.h286
-rw-r--r--src/base.cpp287
-rw-r--r--src/boolmember.h67
-rw-r--r--src/callable.cpp133
-rw-r--r--src/callable.h190
-rw-r--r--src/classbase.cpp130
-rw-r--r--src/classimpl.cpp1429
-rw-r--r--src/classimpl.h445
-rw-r--r--src/extension.cpp103
-rw-r--r--src/extensionimpl.cpp300
-rw-r--r--src/extensionimpl.h213
-rw-r--r--src/floatmember.h67
-rw-r--r--src/function.h102
-rw-r--r--src/global.cpp45
-rw-r--r--src/globals.cpp92
-rw-r--r--src/hashiterator.h250
-rw-r--r--src/hashmember.cpp40
-rw-r--r--src/includes.h121
-rw-r--r--src/init.h54
-rw-r--r--src/invaliditerator.h82
-rw-r--r--src/iteratorimpl.cpp183
-rw-r--r--src/iteratorimpl.h190
-rw-r--r--src/member.h77
-rw-r--r--src/members.cpp90
-rw-r--r--src/method.h139
-rw-r--r--src/modifiers.cpp39
-rw-r--r--src/namespace.cpp134
-rw-r--r--src/notimplemented.h51
-rw-r--r--src/nullmember.h59
-rw-r--r--src/numericmember.h67
-rw-r--r--src/object.cpp79
-rw-r--r--src/objectimpl.h204
-rw-r--r--src/origexception.h145
-rw-r--r--src/parametersimpl.h53
-rw-r--r--src/property.h160
-rw-r--r--src/streambuf.cpp93
-rw-r--r--src/streambuf.h80
-rw-r--r--src/streams.cpp40
-rw-r--r--src/stringmember.h83
-rw-r--r--src/super.cpp71
-rw-r--r--src/traverseiterator.h259
-rw-r--r--src/value.cpp1911
-rw-r--r--src/valueiterator.cpp100
-rw-r--r--src/valueiteratorimpl.h71
44 files changed, 0 insertions, 8814 deletions
diff --git a/src/arithmetic.h b/src/arithmetic.h
deleted file mode 100644
index 20e346e..0000000
--- a/src/arithmetic.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/**
- * Arithmethic.h
- *
- * Helper class that takes care of arithmetic operations on PHP variables
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-template < template<typename T> class F>
-class Arithmetic
-{
-public:
- /**
- * Constructor
- * @param value The original object
- */
- Arithmetic(Value *value) : _value(value) {}
-
- /**
- * Destructor
- */
- virtual ~Arithmetic() {}
-
- /**
- * Apply a number, and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(const Value &value)
- {
- // is this a type a floating point type?
- if (value.isFloat()) return apply(value.floatValue());
-
- // we are going to treat it as a numeric (non floating) type
- return apply(value.numericValue());
- }
-
- /**
- * Apply a number, and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(int16_t value)
- {
- // check if the current object is a floating point number
- if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value));
-
- // apply to natural numbers
- return Value(F<int64_t>()(_value->numericValue(), value));
- }
-
- /**
- * Apply a number, and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(int32_t value)
- {
- // check if the current object is a floating point number
- if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value));
-
- // apply to natural numbers
- return Value(F<int64_t>()(_value->numericValue(), value));
- }
-
- /**
- * Apply a number, and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(int64_t value)
- {
- // check if the current object is a floating point number
- if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value));
-
- // apply to natural numbers
- return Value(F<int64_t>()(_value->numericValue(), value));
- }
-
- /**
- * Apply a boolean (treat is as 0 or 1), and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(bool value)
- {
- // check if the current object is a floating point number
- if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), value?1:0));
-
- // apply to natural numbers
- return Value(F<int64_t>()(_value->numericValue(), value?1:0));
- }
-
- /**
- * Apply a character (value between '0' and '9'), and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(char value)
- {
- // convert to an integer
- int v = value < '0' || value > '9' ? 0 : value - '0';
-
- // check if the current object is a floating point number
- if (_value->isFloat()) return Value(F<double>()(_value->floatValue(), v));
-
- // apply to natural numbers
- return Value(F<int64_t>()(_value->numericValue(), v));
- }
-
- /**
- * Apply a string (representing a number), and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(const std::string &value)
- {
- // convert string to integer
- return apply(atoi(value.c_str()));
- }
-
- /**
- * Apply a string (representing a number), and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(const char *value)
- {
- // convert string to integer
- return apply(atoi(value));
- }
-
- /**
- * Apply a string (representing a number), and return a new value object after running the arithmetic function
- * @param value
- * @return Value
- */
- Value apply(double value)
- {
- return Value(F<double>()(_value->floatValue(), value));
- }
-
- /**
- * Assign a different value object, applying the arithmetic operation
- * @param value
- * @return Value
- */
- Value &assign(const Value &value)
- {
- // is this a type a floating point type?
- if (value.isFloat()) return assign(value.floatValue());
-
- // we are going to treat it as a numeric (non floating) type
- return assign(value.numericValue());
- }
-
- /**
- * Assign a 16bit number, applying the arithmetic operation
- * @param value
- * @return Value
- */
- Value &assign(int16_t value)
- {
- // is the current object a floating point type?
- if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value));
-
- // do a numeric operation
- return _value->operator=(F<int64_t>()(_value->numericValue(), value));
- }
-
- /**
- * Assign 32bit integer, applying the arithmetic operation
- * @param value
- * @return Value
- */
- Value &assign(int32_t value)
- {
- // is the current object a floating point type?
- if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value));
-
- // do a numeric operation
- return _value->operator=(F<int64_t>()(_value->numericValue(), value));
- }
-
- /**
- * Assign 64bit integer, applying the arithmetic operation
- * @param value
- * @return Value
- */
- Value &assign(int64_t value)
- {
- // is the current object a floating point type?
- if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value));
-
- // do a numeric operation
- return _value->operator=(F<int64_t>()(_value->numericValue(), value));
- }
-
- /**
- * Assign 64bit integer - which is treated as 1 or 0 - applying the arithmetic operation
- * @param value
- * @return Value
- */
- Value &assign(bool value)
- {
- // is the current object a floating point type?
- if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), value?1:0));
-
- // do a numeric operation
- return _value->operator=(F<int64_t>()(_value->numericValue(), value?1:0));
- }
-
- /**
- * Assign a single character - which is treated as an int, and applying the arithmetic function
- * @param value
- * @return Value
- */
- Value &assign(char value)
- {
- // convert to an integer
- int v = value < '0' || value > '9' ? 0 : value - '0';
-
- // is the current object a floating point type?
- if (_value->isFloat()) return _value->operator=(F<double>()(_value->floatValue(), v));
-
- // do a numeric operation
- return _value->operator=(F<int64_t>()(_value->numericValue(), v));
- }
-
- /**
- * Assign a a string - treating it as an integer, and applying the arithmetic function
- * @param value
- * @return Value
- */
- Value &assign(const std::string &value)
- {
- // assign integer
- return assign(atoi(value.c_str()));
- }
-
- /**
- * Assign a string - treating it as an integer, and applying the arithmetic function
- * @param value
- * @return Value
- */
- Value &assign(const char *value)
- {
- // assign integer
- return assign(atoi(value));
- }
-
- /**
- * Assign a double, applying the arithmetic operation
- * @param value
- * @return Value
- */
- Value &assign(double value)
- {
- // do float operation
- return _value->operator=(F<double>()(_value->floatValue(), value));
- }
-
-private:
- /**
- * Pointer to the original value object
- * @var Value
- */
- Value *_value;
-
-
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/base.cpp b/src/base.cpp
deleted file mode 100644
index 5d15011..0000000
--- a/src/base.cpp
+++ /dev/null
@@ -1,287 +0,0 @@
-/**
- * Base.cpp
- *
- * Implementation file for the base of all classes
- *
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Store the object in the PHP object cache
- * @param entry Class entry
- * @param tsrm_ls
- * @return MixedObject
- */
-//MixedObject *Base::store(zend_class_entry *entry TSRMLS_DC)
-//{
-// // allocate memory for the object
-// MixedObject *result = (MixedObject *)emalloc(sizeof(MixedObject));
-//
-// // store the new c++ object
-// result->cpp = this;
-//
-// // store the class entry in the newly created object
-// result->php.ce = entry;
-//
-// // initialize the object
-// zend_object_std_init(&result->php, entry TSRMLS_CC);
-//
-//#if PHP_VERSION_ID < 50399
-//
-// // tmp variable
-// zval *tmp;
-//
-// // initialize the properties, php 5.3 way
-// zend_hash_copy(result->php.properties, &entry->default_properties, (copy_ctor_func_t) zval_property_ctor, &tmp, sizeof(zval*));
-//
-//#else
-//
-// // version higher than 5.3 have an easier way to initialize
-// object_properties_init(&result->php, entry);
-//
-//#endif
-//
-//#ifdef ZTS
-//
-// // when in thread safety mode, the destruct method and free method have
-// // an extra parameter holding thread information
-// using DestructType = void(zend_object*,unsigned int,void***);
-// using FreeType = void(zend_object*,void***);
-//
-//#else
-//
-// // not in thread mode: no special parameter for the tsrm_ls variable
-// using DestructType = void(zend_object*,unsigned int);
-// using FreeType = void(zend_object*);
-//
-//#endif
-//
-// // store the two destruct methods in temporary vars
-// DestructType *destructMethod = &ClassImpl::destructObject;
-// FreeType *freeMethod = &ClassImpl::freeObject;
-//
-// // the destructor and clone handlers are set to NULL. I dont know why, but they do not
-// // seem to be necessary...
-// _handle = zend_objects_store_put(result, (zend_objects_store_dtor_t)destructMethod, (zend_objects_free_object_storage_t)freeMethod, NULL TSRMLS_CC);
-//
-// // done
-// return result;
-//}
-
-/**
- * Overridable method that is called right before an object is destructed
- */
-void Base::__destruct() const
-{
- // throw exception, so that the PHP-CPP library will check if the user
- // somehow registered an explicit __destruct method
- throw NotImplemented();
-}
-
-/**
- * Overridable method that is called to check if a property is set
- *
- * The default implementation does nothing, and the script will fall back
- * to accessing the regular object properties
- *
- * @param key
- * @return bool
- */
-bool Base::__isset(const Php::Value &key) const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the unset function can be called
- throw NotImplemented();
-}
-
-/**
- * Overridable method that is called to set a new property
- *
- * The default implementation does nothing, and the script will fall back
- * to accessing the regular object properties
- *
- * @param key
- * @param value
- */
-void Base::__set(const Php::Value &key, const Php::Value &value) const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the unset function can be called
- throw NotImplemented();
-}
-
-/**
- * Retrieve a property
- *
- * The default implementation does nothing, and the script will fall back
- * to accessing the regular object properties
- *
- * @param key
- * @return value
- */
-Php::Value Base::__get(const Php::Value &key) const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return nullptr;
-}
-
-/**
- * Remove a member
- *
- * The default implementation does nothing, and the script will fall back
- * to accessing the regular object properties
- *
- * @param key
- */
-void Base::__unset(const Php::Value &key) const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-}
-
-/**
- * Call a method
- *
- * This method is called when a method is called from the PHP script that
- * was not explicitly defined. You can use this to catch variable method
- * names, or to support all thinkable method names.
- *
- * @param method Name of the method that was called
- * @param params The parameters that were passed to the function
- * @return Value The return value
- */
-Value Base::__call(const char *method, Parameters &params) const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return nullptr;
-}
-
-/**
- * Call the class as if it was a function
- *
- * This method is called when a an object is used with () operators:
- * $object(). You can override this method to make objects callable.
- *
- * @param params The parameters that were passed to the function
- * @return Value The return value
- */
-Value Base::__invoke(Parameters &params) const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return nullptr;
-}
-
-/**
- * Cast the object to a string
- *
- * This method is called when an object is casted to a string, or when
- * it is used in a string context
- *
- * @return Value The object as a string
- */
-Value Base::__toString() const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return nullptr;
-}
-
-/**
- * Cast the object to an integer
- *
- * This method is called when an object is casted to an integer, or when
- * it is used in an integer context
- *
- * @return int Integer value
- */
-Value Base::__toInteger() const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return 0;
-}
-
-/**
- * Cast the object to a float
- *
- * This method is called when an object is casted to a float, or when it
- * is used in a float context
- *
- * @return double Floating point value
- */
-Value Base::__toFloat() const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return 0.0;
-}
-
-/**
- * Cast the object to a boolean
- *
- * This method is called when an object is casted to a bool, or when it
- * is used in a boolean context
- *
- * @return bool
- */
-Value Base::__toBool() const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return false;
-}
-
-/**
- * Compare the object with a different object
- *
- * Check how a different object compares to this object
- *
- * @param that Object to compare with
- * @return int
- */
-int Base::__compare(const Base &that) const
-{
- // throw an exception that will be caught in the ClassBase class,
- // so that the default implementation of the function can be called
- throw NotImplemented();
-
- // unreachable code
- return 1;
-}
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/boolmember.h b/src/boolmember.h
deleted file mode 100644
index 5b5d43d..0000000
--- a/src/boolmember.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * BoolMember.h
- *
- * Implementation for a property that is initially set to a boolean value
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class BoolMember : public Member
-{
-private:
- /**
- * The value
- * @var bool
- */
- bool _value;
-
-public:
- /**
- * Constructor
- * @param name
- * @param value
- * @param flags
- */
- BoolMember(const char *name, bool value, int flags) : Member(name, flags), _value(value) {}
-
- /**
- * Destructor
- */
- virtual ~BoolMember() {}
-
- /**
- * Virtual method to declare a class constant
- * @param entry Class entry
- * @param tsrm_ls
- */
- virtual void constant(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- zend_declare_class_constant_bool(entry, _name.c_str(), _name.size(), _value TSRMLS_CC);
- }
-
- /**
- * Virtual method to declare the property
- * @param entry Class entry
- * @param tsrm_ls
- */
- virtual void declare(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- // char* cast is necessary for php 5.3
- zend_declare_property_bool(entry, (char *)_name.c_str(), _name.size(), _value, _flags TSRMLS_CC);
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/callable.cpp b/src/callable.cpp
deleted file mode 100644
index 737b85b..0000000
--- a/src/callable.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-/**
- * Function.cpp
- *
- * Implementation for the function class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Function that is called by the Zend engine every time that a function gets called
- * @param ht
- * @param return_value
- * @param return_value_ptr
- * @param this_ptr
- * @param return_value_used
- * @param tsrm_ls
- * @return integer
- */
-static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS)
-{
- // find the function name
- const char *name = get_active_function_name(TSRMLS_C);
-
- // uncover the hidden pointer inside the function name
- Callable *callable = HiddenPointer<Callable>(name);
-
- // wrap the return value
- Value result(return_value, true);
-
- // construct parameters
- ParametersImpl params(this_ptr, ZEND_NUM_ARGS() TSRMLS_CC);
-
- // the function could throw an exception
- try
- {
- // get the result
- result = callable->invoke(params);
- }
- catch (Exception &exception)
- {
- // process the exception
- process(exception TSRMLS_CC);
- }
-}
-
-/**
- * Fill a function entry
- *
- * This method is called when the extension is registering itself, when the
- * function or method introces himself
- *
- * @param entry Entry to be filled
- * @param classname Optional class name
- * @param flags Is this a public property?
- */
-void Callable::initialize(zend_function_entry *entry, const char *classname, int flags) const
-{
- // fill the members of the entity, and hide a pointer to the current object in the name
- entry->fname = (const char *)_ptr;
- entry->handler = invoke_callable;
- entry->arg_info = _argv;
- entry->num_args = _argc;
- entry->flags = flags;
-
- // we should fill the first argument as well
- initialize((zend_arg_info *)entry->arg_info, classname);
-}
-
-/**
- * Fill a function entry
- * @param info Info to be filled
- * @param classname Optional classname
- */
-void Callable::initialize(zend_arg_info *info, const char *classname) const
-{
-#if PHP_VERSION_ID >= 50400
- // up until php 5.3, the first info object is filled with alternative information,
- // later it is casted to a zend_internal_function object
- auto *finfo = (zend_internal_function_info *)info;
-
- // fill in all the members, note that return reference is false by default,
- // because we do not support returning references in PHP-CPP, although Zend
- // engine allows it. Inside the name we hide a pointer to the current object
- finfo->_name = _ptr;
- finfo->_name_len = strlen(_ptr);
- finfo->_class_name = classname;
-
- // number of required arguments, and the expected return type
- finfo->required_num_args = _required;
- finfo->_type_hint = (unsigned char)_return;
-
- // we do not support return-by-reference
- finfo->return_reference = false;
-
-# if PHP_VERSION_ID >= 50600
- // since php 5.6 there are _allow_null and _is_variadic properties. It's
- // not exactly clear what they do (@todo find this out) so for now we set
- // them to false
- finfo->_allow_null = false;
- finfo->_is_variadic = false;
-
-# else
- // passing by reference is not used (only for php 5.4 and php 5.5)
- finfo->pass_rest_by_reference = false;
-# endif
-
-#else
- // php 5.3 code
- info->name = nullptr;
- info->name_len = 0;
- info->class_name = nullptr;
- info->class_name_len = 0;
- info->array_type_hint = false;
- info->allow_null = false;
- info->pass_by_reference = false;
- info->return_reference = false;
- info->required_num_args = _required;
-#endif
-}
-
-/**
- * End of namespace
- */
-}
-
-
diff --git a/src/callable.h b/src/callable.h
deleted file mode 100644
index 65ce719..0000000
--- a/src/callable.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/**
- * Callable.h
- *
- * Object represents a callable function or method that is defined with the CPP
- * API.
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class Callable
-{
-public:
- /**
- * Constructor
- * @param name Function or method name
- * @param arguments Information about the arguments
- */
- Callable(const char *name, const Arguments &arguments = {}) : _ptr(this, name)
- {
- // construct vector for arguments
- _argc = arguments.size();
- _argv = new zend_arg_info[_argc+1];
-
- // the first record is initialized with information about the function,
- // so we skip that here
- int i=1;
-
- // loop through the arguments
- for (auto it = arguments.begin(); it != arguments.end(); it++)
- {
- // increment counter with number of required parameters
- if (it->required()) _required++;
-
- // fill the arg info
- fill(&_argv[i], *it);
- }
- }
-
- /**
- * Copy constructor
- * @param that
- */
- Callable(const Callable &that) :
- _ptr(that._ptr),
- _return(that._return),
- _required(that._required),
- _argc(that._argc),
- _argv(nullptr) {}
-
- /**
- * Move constructor
- * @param that
- */
- Callable(Callable &&that) :
- _ptr(std::move(that._ptr)),
- _return(that._return),
- _required(that._required),
- _argc(that._argc),
- _argv(that._argv)
- {
- // invalidate other object
- that._argv = nullptr;
- }
-
- /**
- * Destructor
- */
- virtual ~Callable()
- {
- if (_argv) delete[] _argv;
- }
-
- /**
- * Method that gets called every time the function is executed
- * @param params The parameters that were passed
- * @return Variable Return value
- */
- virtual Value invoke(Parameters &params) = 0;
-
- /**
- * Fill a function entry
- * @param entry Entry to be filled
- * @param ns Active namespace
- * @param classname Optional class name
- * @param flags Access flags
- */
- void initialize(zend_function_entry *entry, const char *classname = nullptr, int flags = 0) const;
-
- /**
- * Fill function info
- * @param info Info object to be filled
- * @param ns Active namespace
- * @param classname Optional class name
- */
- void initialize(zend_arg_info *info, const char *classname = nullptr) const;
-
-
-protected:
- /**
- * Hidden pointer to the name and the function
- * @var HiddenPointer
- */
- HiddenPointer<Callable> _ptr;
-
- /**
- * Suggestion for the return type
- * @var Type
- */
- Type _return = Type::Null;
-
- /**
- * Required number of arguments
- * @var integer
- */
- int _required = 0;
-
- /**
- * Total number of arguments
- * @var integer
- */
- int _argc = 0;
-
- /**
- * The arguments
- * @var zend_arg_info[]
- */
- zend_arg_info *_argv = nullptr;
-
- /**
- * Private helper method to fill an argument object
- * @param info object from the zend engine
- * @param arg original object
- */
- void fill(zend_arg_info *info, const Argument &arg) const
- {
- // fill members
- info->name = arg.name().c_str();
- info->name_len = arg.name().size();
-
-#if PHP_VERSION_ID >= 50400
-
- // since php 5.4 there is a type-hint, but we only support arrays, objects and callables
- switch (arg.type()) {
- case Type::Array: info->type_hint = IS_ARRAY; break;
- case Type::Callable: info->type_hint = IS_CALLABLE; break;
- case Type::Object: info->type_hint = IS_OBJECT; break;
- default: info->type_hint = IS_NULL; break;
- }
-
-# if PHP_VERSION_ID >= 50600
-
- // from PHP 5.6 and onwards, an is_variadic property can be set, this
- // specifies whether this argument is the first argument that specifies
- // the type for a variable length list of arguments. For now we only
- // support methods and functions with a fixed number of arguments.
- info->is_variadic = false;
-
-# endif
-
-#else
-
- // php 5.3 code
- info->array_type_hint = type == Type::Array;
- info->return_reference = false;
- info->required_num_args = 0; // @todo is this correct?
-
-#endif
-
- // this parameter is a regular type
- info->class_name = arg.type() == Type::Object ? arg.classname().c_str() : nullptr;
- info->class_name_len = arg.type() == Type::Object ? arg.classname().size() : 0;
- info->allow_null = arg.allowNull();
- info->pass_by_reference = arg.byReference();
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/classbase.cpp b/src/classbase.cpp
deleted file mode 100644
index 18d81d5..0000000
--- a/src/classbase.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * ClassBase.cpp
- *
- * Implementation of the ClassBase class.
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Protected constructor
- * @param classname Class name
- * @param flags Class flags
- */
-ClassBase::ClassBase(const char *classname, int flags)
-{
- // the flags hold a method-flag-value, this should be converted into a class-type
- if (flags & Abstract) _impl = std::make_shared<ClassImpl>(classname, ClassType::Abstract);
- else if (flags & Final) _impl = std::make_shared<ClassImpl>(classname, ClassType::Final);
- else _impl = std::make_shared<ClassImpl>(classname, ClassType::Regular);
-}
-
-/**
- * Protected constructor
- * @param classname Class name
- * @param type Class type
- */
-ClassBase::ClassBase(const char *classname, ClassType type)
-{
- // construct implementation
- _impl = std::make_shared<ClassImpl>(classname, type);
-}
-
-/**
- * Function that can be called by a derived method when a certain function
- * is not implemented
- */
-void ClassBase::notImplemented()
-{
- // throw an exception
- throw NotImplemented();
-}
-
-/**
- * Add a method to the class
- * @param name Name of the method
- * @param method The actual method
- * @param flags Optional flags
- * @param args Description of the supported arguments
- */
-void ClassBase::method(const char *name, const method_callback_0 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-void ClassBase::method(const char *name, const method_callback_1 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-void ClassBase::method(const char *name, const method_callback_2 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-void ClassBase::method(const char *name, const method_callback_3 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-void ClassBase::method(const char *name, const method_callback_4 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-void ClassBase::method(const char *name, const method_callback_5 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-void ClassBase::method(const char *name, const method_callback_6 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-void ClassBase::method(const char *name, const method_callback_7 &callback, int flags, const Arguments &args) { _impl->method(name, callback, flags, args); }
-
-/**
- * Add a static method to the class
- * @param name Name of the method
- * @param method The actual method
- * @param flags Optional flags
- * @param args Description of the supported arguments
- */
-void ClassBase::method(const char *name, const native_callback_0 &method, int flags, const Arguments &args) { _impl->method(name, method, flags, args); }
-void ClassBase::method(const char *name, const native_callback_1 &method, int flags, const Arguments &args) { _impl->method(name, method, flags, args); }
-void ClassBase::method(const char *name, const native_callback_2 &method, int flags, const Arguments &args) { _impl->method(name, method, flags, args); }
-void ClassBase::method(const char *name, const native_callback_3 &method, int flags, const Arguments &args) { _impl->method(name, method, flags, 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 ClassBase::method(const char *name, int flags, const Arguments &args) { _impl->method(name, flags, args); }
-
-/**
- * Add a property to the class
- * @param name Name of the property
- * @param value Actual property value
- * @param flags Optional flags
- */
-void ClassBase::property(const char *name, std::nullptr_t value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, int16_t value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, int32_t value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, int64_t value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, bool value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, char value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, const std::string &value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, const char *value, int flags) { _impl->property(name, value, flags); }
-void ClassBase::property(const char *name, double value, int flags) { _impl->property(name, value, flags); }
-
-/**
- * Set property with callbacks
- * @param name Name of the property
- * @param getter Getter method
- */
-void ClassBase::property(const char *name, const getter_callback_0 &getter) { _impl->property(name, getter); }
-void ClassBase::property(const char *name, const getter_callback_1 &getter) { _impl->property(name, getter); }
-void ClassBase::property(const char *name, const getter_callback_0 &getter, const setter_callback_0 &setter) { _impl->property(name, getter, setter); }
-void ClassBase::property(const char *name, const getter_callback_1 &getter, const setter_callback_0 &setter) { _impl->property(name, getter, setter); }
-void ClassBase::property(const char *name, const getter_callback_0 &getter, const setter_callback_1 &setter) { _impl->property(name, getter, setter); }
-void ClassBase::property(const char *name, const getter_callback_1 &getter, const setter_callback_1 &setter) { _impl->property(name, getter, setter); }
-
-/**
- * Add an interface
- * @param interface Interface object
- */
-void ClassBase::implements(const ClassBase &interface) { _impl->implements(interface._impl); }
-
-/**
- * Set the base class
- * @param base Php::Class object that is the base
- */
-void ClassBase::extends(const ClassBase &base) { _impl->extends(base._impl); }
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/classimpl.cpp b/src/classimpl.cpp
deleted file mode 100644
index d63956a..0000000
--- a/src/classimpl.cpp
+++ /dev/null
@@ -1,1429 +0,0 @@
-/**
- * ClassImpl.cpp
- *
- * Implementation file for the ClassImpl class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Destructor
- */
-ClassImpl::~ClassImpl()
-{
- // destruct the entries
- if (_entries) delete[] _entries;
-
- // php 5.3 deallocates the doc_comment by iself
-#if PHP_VERSION_ID >= 50400
- if (_comment) free(_comment);
-#endif
-}
-
-/**
- * @todo refactor so that methods become simpler
- */
-
-/**
- * Retrieve our C++ implementation object
- * @param entry
- * @return ClassImpl
- */
-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)
- while (entry->parent) entry = entry->parent;
-
-#if PHP_VERSION_ID >= 50400
- // retrieve the comment (it has a pointer hidden in it to the ClassBase object)
- const char *comment = entry->info.user.doc_comment;
-#else
- // retrieve the comment php5.3 style (it has a pointer hidden in it to the ClassBase object)
- const char *comment = entry->doc_comment;
-#endif
-
- // the first byte of the comment is an empty string (null character), but
- // the next bytes contain a pointer to the ClassBase class
- return *((ClassImpl **)(comment + 1));
-}
-
-/**
- * Extended zend_internal_function structure that we use to store an
- * instance of the ClassBase object. We need this for static method calls
- */
-struct CallData
-{
- // the internal function is the first member, so
- // that it is possible to cast an instance of this
- // struct to a zend_internal_function
- zend_internal_function func;
-
- // and a pointer to the ClassImpl object
- ClassImpl *self;
-};
-
-/**
- * Handler function that runs the __call function
- * @param ... All normal parameters for function calls
- */
-void ClassImpl::callMethod(INTERNAL_FUNCTION_PARAMETERS)
-{
- // retrieve the originally called (and by us allocated) function object
- // (this was copied from the zend engine source code, code looks way too
- // ugly to be made by me)
- CallData *data = (CallData *)EG(current_execute_data)->function_state.function;
- zend_internal_function *func = &data->func;
-
- // retrieve the function name
- const char *name = func->function_name;
- ClassBase *meta = data->self->_base;
-
- // the data structure was allocated by ourselves in the getMethod or
- // getStaticMethod functions, we no longer need it now
- efree(data);
-
- // the function could throw an exception
- try
- {
- // wrap the return value
- Value result(return_value, true);
-
- // construct parameters
- ParametersImpl params(this_ptr, ZEND_NUM_ARGS() TSRMLS_CC);
-
- // retrieve the base object
- Base *base = params.object();
-
- // is this a static, or a non-static call?
- if (base) result = meta->callCall(base, name, params);
- else result = meta->callCallStatic(name, params);
- }
- catch (const NotImplemented &exception)
- {
- // because of the two-step nature, we are going to report the error ourselves
- zend_error(E_ERROR, "Undefined method %s", name);
- }
- catch (Exception &exception)
- {
- // process the exception
- process(exception TSRMLS_CC);
- }
-}
-
-/**
- * Handler function that runs the __invoke function
- * @param ... All normal parameters for function calls
- */
-void ClassImpl::callInvoke(INTERNAL_FUNCTION_PARAMETERS)
-{
- // retrieve the originally called (and by us allocated) function object
- // (this was copied from the zend engine source code, code looks way too
- // ugly to be made by me)
- CallData *data = (CallData *)EG(current_execute_data)->function_state.function;
-
- // get self reference
- ClassBase *meta = data->self->_base;
-
- // the data structure was allocated by ourselves in the getMethod or
- // getStaticMethod functions, we no longer need it now
- efree(data);
-
- // the function could throw an exception
- try
- {
- // wrap the return value
- Value result(return_value, true);
-
- // construct parameters
- ParametersImpl params(this_ptr, ZEND_NUM_ARGS() TSRMLS_CC);
-
- // retrieve the base object
- Base *base = params.object();
-
- // call the actual __invoke method on the base object
- result = meta->callInvoke(base, params);
- }
- catch (const NotImplemented &exception)
- {
- // because of the two-step nature, we are going to report the error ourselves
- zend_error(E_ERROR, "Function name must be a string");
- }
- catch (Exception &exception)
- {
- // process the exception
- process(exception TSRMLS_CC);
- }
-}
-
-/**
- * Method that returns the function definition of the __call function
- * @param object_ptr
- * @param method_name
- * @param method_len
- * @param tsrm_ls
- * @return zend_function
- */
-#if PHP_VERSION_ID < 50399
-zend_function *ClassImpl::getMethod(zval **object_ptr, char *method_name, int method_len TSRMLS_DC)
-#else
-zend_function *ClassImpl::getMethod(zval **object_ptr, char *method_name, int method_len, const zend_literal *key TSRMLS_DC)
-#endif
-{
- // something strange about the Zend engine (once more). The structure with
- // object-handlers has a get_method and call_method member. When a function is
- // called, the get_method function is called first, to retrieve information
- // about the method (like the handler that should be called to execute it),
- // after that, this returned handler is also called. The call_method property
- // of the object_handlers structure however, never gets called. Typical.
-
- // first we'll check if the default handler does not have an implementation,
- // in that case the method is probably already implemented as a regular method
-#if PHP_VERSION_ID < 50399
- auto *defaultFunction = std_object_handlers.get_method(object_ptr, method_name, method_len TSRMLS_CC);
-#else
- auto *defaultFunction = std_object_handlers.get_method(object_ptr, method_name, method_len, key TSRMLS_CC);
-#endif
-
- // did the default implementation do anything?
- if (defaultFunction) return defaultFunction;
-
- // retrieve the class entry linked to this object
- auto *entry = zend_get_class_entry(*object_ptr TSRMLS_CC);
-
- // this is peculiar behavior of the zend engine, we first are going to dynamically
- // allocate memory holding all the properties of the __call method (we initially
- // had an implementation here that used a static variable, and that worked too,
- // but we'll follow thread safe implementation of the Zend engine here, although
- // it is strange to allocate and free memory in one and the same method call (free()
- // call happens in call_method())
- auto *data = (CallData *)emalloc(sizeof(CallData));
- auto *function = &data->func;
-
- // we're going to set all properties
- function->type = ZEND_INTERNAL_FUNCTION;
- function->module = nullptr;
- function->handler = &ClassImpl::callMethod;
- function->arg_info = nullptr;
- function->num_args = 0;
- function->required_num_args = 0;
- function->scope = entry;
- function->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
- function->function_name = method_name;
-
- // store pointer to ourselves
- 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)
- return (zend_function *)data;
-}
-
-/**
- * Method that is called right before a static method call is attempted
- * @param entry
- * @param method
- * @param method_len
- * @param tsrm_ls
- * @return zend_function
- */
-zend_function *ClassImpl::getStaticMethod(zend_class_entry *entry, char* method, int method_len TSRMLS_DC)
-{
- // first we'll check if the default handler does not have an implementation,
- // in that case the method is probably already implemented as a regular method
-#if PHP_VERSION_ID < 50399
- auto *defaultFunction = zend_std_get_static_method(entry, method, method_len TSRMLS_CC);
-#else
- auto *defaultFunction = zend_std_get_static_method(entry, method, method_len, nullptr TSRMLS_CC);
-#endif
-
- // did the default implementation do anything?
- if (defaultFunction) return defaultFunction;
-
- // just like we did in getMethod() (see comment there) we are going to dynamically
- // allocate data holding information about the function
- auto *data = (CallData *)emalloc(sizeof(CallData));
- auto *function = &data->func;
-
- // we're going to set all properties
- function->type = ZEND_INTERNAL_FUNCTION;
- function->module = nullptr;
- function->handler = ClassImpl::callMethod;
- function->arg_info = nullptr;
- function->num_args = 0;
- function->required_num_args = 0;
- function->scope = nullptr;
- function->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
- function->function_name = method;
-
- // store pointer to ourselves
- 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)
- return (zend_function *)data;
-}
-
-/**
- * Method that returns the closure -- this is the __invoke handler!
- * @param object
- * @param entry_ptr
- * @param func
- * @param object_ptr
- * @param tsrm_ls
- * @return int
- */
-int ClassImpl::getClosure(zval *object, zend_class_entry **entry_ptr, zend_function **func, zval **object_ptr TSRMLS_DC)
-{
- // it is really unbelievable how the Zend engine manages to implement every feature
- // in a complete different manner. You would expect the __invoke() and the
- // __call() functions not to be very different from each other. However, they
- // both have a completely different API. This getClosure method is supposed
- // to fill the function parameter with all information about the invoke()
- // method that is going to get called
-
- // retrieve the class entry linked to this object
- auto *entry = zend_get_class_entry(object TSRMLS_CC);
-
- // just like we did for getMethod(), we're going to dynamically allocate memory
- // with all information about the function
- auto *data = (CallData *)emalloc(sizeof(CallData));
- auto *function = &data->func;
-
- // we're going to set all properties
- function->type = ZEND_INTERNAL_FUNCTION;
- function->module = nullptr;
- function->handler = &ClassImpl::callInvoke;
- function->arg_info = nullptr;
- function->num_args = 0;
- function->required_num_args = 0;
- function->scope = entry;
- function->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
- function->function_name = nullptr;
-
- // store pointer to ourselves
- 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
- // zend_function union
- *func = (zend_function *)data;
-
- // the object_ptr should be filled with the object on which the method is
- // called (otherwise the Zend engine tries to call the method statically)
- *object_ptr = object;
-
- // done
- return SUCCESS;
-};
-
-/**
- * Retrieve pointer to our own object handlers
- * @return zend_object_handlers
- */
-zend_object_handlers *ClassImpl::objectHandlers()
-{
- // keep static structure
- static zend_object_handlers handlers;
-
- // is the object already initialized?
- static bool initialized = false;
-
- // already initialized?
- if (initialized) return &handlers;
-
- // initialize the handlers
- memcpy(&handlers, &std_object_handlers, sizeof(zend_object_handlers));
-
- // install custom clone function
- if (!_base->clonable()) handlers.clone_obj = nullptr;
- else handlers.clone_obj = &ClassImpl::cloneObject;
-
- // functions for the Countable interface
- handlers.count_elements = &ClassImpl::countElements;
-
- // functions for the ArrayAccess interface
- handlers.write_dimension = &ClassImpl::writeDimension;
- handlers.read_dimension = &ClassImpl::readDimension;
- handlers.has_dimension = &ClassImpl::hasDimension;
- handlers.unset_dimension = &ClassImpl::unsetDimension;
-
- // functions for the magic properties handlers (__get, __set, __isset and __unset)
- handlers.write_property = &ClassImpl::writeProperty;
- handlers.read_property = &ClassImpl::readProperty;
- handlers.has_property = &ClassImpl::hasProperty;
- handlers.unset_property = &ClassImpl::unsetProperty;
-
- // when a method is called (__call and __invoke)
- handlers.get_method = &ClassImpl::getMethod;
- handlers.get_closure = &ClassImpl::getClosure;
-
- // handler to cast to a different type
- handlers.cast_object = &ClassImpl::cast;
-
- // method to compare two objects
- handlers.compare_objects = &ClassImpl::compare;
-
- // remember that object is now initialized
- initialized = true;
-
- // done
- return &handlers;
-}
-
-/**
- * Function to compare two objects
- * @param val1
- * @param val2
- * @param tsrm_ls
- * @return int
- */
-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(val1 TSRMLS_CC);
-
- // other object must be of the same type
- if (entry != zend_get_class_entry(val2 TSRMLS_CC)) throw NotImplemented();
-
- // we need the C++ class meta-information object
- ClassBase *meta = self(entry)->_base;
-
- // get the base objects
- Base *object1 = ObjectImpl::find(val1 TSRMLS_CC)->object();
- Base *object2 = ObjectImpl::find(val2 TSRMLS_CC)->object();
-
- // run the compare method
- return meta->callCompare(object1, object2);
- }
- catch (const NotImplemented &exception)
- {
- // it was not implemented, do we have a default?
- if (!std_object_handlers.compare_objects) return 1;
-
- // call default
- return std_object_handlers.compare_objects(val1, val2 TSRMLS_CC);
- }
- catch (Exception &exception)
- {
- // a Php::Exception was thrown by the extension __compare function,
- // pass this on to user space
- process(exception TSRMLS_CC);
-
- // what shall we return here...
- return 1;
- }
-}
-
-/**
- * Function to cast the object to a different type
- * @param val
- * @param retval
- * @param type
- * @param tsrm_ls
- * @return int
- */
-int ClassImpl::cast(zval *val, zval *retval, int type TSRMLS_DC)
-{
- // 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(val TSRMLS_CC);
-
- // we need the C++ class meta-information object
- 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
- // functions in the Zend engine that have a comparable API
- INIT_PZVAL(retval);
-
- // wrap zval in value object
- Value result(retval, true);
-
- // when the magic function it not implemented, an exception will be thrown,
- // and the extension may throw a Php::Exception
- try
- {
- // the result zval
- zval *result = nullptr;
-
- // check type
- switch ((Type)type) {
- 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 original parameter overwritten?
- if (val == retval) zval_dtor(val);
-
- // overwrite the result
- ZVAL_ZVAL(retval, result, 1, 1);
-
- // done
- return SUCCESS;
- }
- catch (const NotImplemented &exception)
- {
- // is there a default?
- if (!std_object_handlers.cast_object) return FAILURE;
-
- // call default
- return std_object_handlers.cast_object(val, retval, type TSRMLS_CC);
- }
- catch (Exception &exception)
- {
- // pass on the exception to php userspace
- process(exception TSRMLS_CC);
-
- // done
- return FAILURE;
- }
-}
-
-/**
- * Function that is called to create space for a cloned object
- * @param val The object to be cloned
- * @return zend_obejct_value The object to be created
- */
-zend_object_value ClassImpl::cloneObject(zval *val TSRMLS_DC)
-{
- // retrieve the class entry linked to this object
- auto *entry = zend_get_class_entry(val TSRMLS_CC);
-
- // we need the C++ class meta-information object
- ClassImpl *impl = self(entry);
- ClassBase *meta = impl->_base;
-
- // retrieve the old object, which we are going to copy
- ObjectImpl *old_object = ObjectImpl::find(val TSRMLS_CC);
-
- // create a new base c++ object
- 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
- // a copy constructor)
- if (!cpp) throw Php::Exception(std::string("Unable to clone ") + entry->name);
-
- // the thing we're going to return
- zend_object_value result;
-
- // set the handlers
- result.handlers = impl->objectHandlers();
-
- // store the object
- ObjectImpl *new_object = new ObjectImpl(entry, cpp TSRMLS_CC);
-
- // store the object in the object cache
- 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);
-
- // was a custom clone method installed? If not we call the magic c++ __clone method
- if (!entry->clone) meta->callClone(cpp);
-
- // done
- return result;
-}
-
-/**
- * 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
- * @return int
- */
-int ClassImpl::countElements(zval *object, long *count TSRMLS_DC)
-{
- // does it implement the countable interface?
- 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)
- {
- // the user function may throw an exception that needs to be processed
- try
- {
- // call the count function
- *count = countable->count();
-
- // done
- return SUCCESS;
- }
- catch (Exception &exception)
- {
- // process the exception
- process(exception TSRMLS_CC);
-
- // unreachable
- return FAILURE;
- }
- }
- else
- {
- // Countable interface was not implemented, check if there is a default
- if (!std_object_handlers.count_elements) return FAILURE;
-
- // call default
- return std_object_handlers.count_elements(object, count TSRMLS_CC);
- }
-}
-
-/**
- * Function that is called when the object is used as an array in PHP
- *
- * This is the [] operator in PHP, and mapped to the offsetGet() method
- * of the ArrayAccess interface
- *
- * @param object The object on which it is called
- * @param offset The name of the property
- * @param type The type of the variable???
- * @param tsrm_ls
- * @return zval
- */
-zval *ClassImpl::readDimension(zval *object, zval *offset, int type TSRMLS_DC)
-{
- // what to do with the type?
- //
- // the type parameter tells us whether the dimension was read in READ
- // mode, WRITE mode, READWRITE mode or UNSET mode.
- //
- // In 99 out of 100 situations, it is called in regular READ mode (value 0),
- // only when it is called from a PHP script that has statements like
- // $x =& $object["x"], $object["x"]["y"] = "something" or unset($object["x"]["y"]),
- // the type parameter is set to a different value.
- //
- // But we must ask ourselves the question what we should be doing with such
- // cases. Internally, the object most likely has a full native implementation,
- // and the property that is returned is just a string or integer or some
- // other value, that is temporary WRAPPED into a zval to make it accessible
- // from PHP. If someone wants to get a reference to such an internal variable,
- // that is in most cases simply impossible.
-
-
- // does it implement the arrayaccess interface?
- 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)
- {
- // the C++ code may throw an exception
- try
- {
- // ArrayAccess is implemented, call function
- return toZval(arrayaccess->offsetGet(offset), type);
- }
- catch (Exception &exception)
- {
- // process the exception (send it to user space)
- process(exception TSRMLS_CC);
-
- // unreachable
- return Value(nullptr).detach();
- }
- }
- else
- {
- // ArrayAccess not implemented, check if there is a default handler
- if (!std_object_handlers.read_dimension) return nullptr;
-
- // call default
- return std_object_handlers.read_dimension(object, offset, type TSRMLS_CC);
- }
-}
-
-/**
- * Function that is called when the object is used as an array in PHP
- *
- * This is the [] operator in PHP, and mapped to the offsetSet() method
- * of the ArrayAccess interface
- *
- * @param object The object on which it is called
- * @param offset The name of the property
- * @param value The new value
- * @param tsrm_ls
- * @return zval
- */
-void ClassImpl::writeDimension(zval *object, zval *offset, zval *value TSRMLS_DC)
-{
- // does it implement the arrayaccess interface?
- 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)
- {
- // method may throw an exception
- try
- {
- // set the value
- arrayaccess->offsetSet(offset, value);
- }
- catch (Exception &exception)
- {
- // process the exception (send it to user space
- process(exception TSRMLS_CC);
- }
- }
- else
- {
- // ArrayAccess not interface, check if there is a default handler
- if (!std_object_handlers.write_dimension) return;
-
- // call the default
- std_object_handlers.write_dimension(object, offset, value TSRMLS_CC);
- }
-}
-
-/**
- * Function that is called when the object is used as an array in PHP
- *
- * This is the [] operator in PHP, and mapped to the offsetExists() method
- * of the ArrayAccess interface
- *
- * @param object The object on which it is called
- * @param member The member to check
- * @param check_empty Was this an isset() call, or an empty() call?
- * @param tsrm_ls
- * @return bool
- */
-int ClassImpl::hasDimension(zval *object, zval *member, int check_empty TSRMLS_DC)
-{
- // does it implement the arrayaccess interface?
- 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)
- {
- // user implemented callbacks could throw an exception
- try
- {
- // check if the member exists
- if (!arrayaccess->offsetExists(member)) return false;
-
- // we know for certain that the offset exists, but should we check
- // more, like whether the value is empty or not?
- if (!check_empty) return true;
-
- // the user wants to know if the property is empty
- return empty(arrayaccess->offsetGet(member));
- }
- catch (Exception &exception)
- {
- // process the exception (send it to user space)
- process(exception TSRMLS_CC);
-
- // unreachable
- return false;
- }
- }
- else
- {
- // ArrayAccess interface is not implemented, check if there is a default handler
- if (!std_object_handlers.has_dimension) return 0;
-
- // call default
- return std_object_handlers.has_dimension(object, member, check_empty TSRMLS_CC);
- }
-}
-
-/**
- * Function that is called when the object is used as an array in PHP
- *
- * This is the [] operator in PHP, and mapped to the offsetUnset() method
- * of the ArrayAccess interface
- *
- * @param object The object on which it is called
- * @param member The member to remove
- * @param tsrm_ls
- */
-void ClassImpl::unsetDimension(zval *object, zval *member TSRMLS_DC)
-{
- // does it implement the arrayaccess interface?
- 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)
- {
- // user implemented code could throw an exception
- try
- {
- // remove the member
- arrayaccess->offsetUnset(member);
- }
- catch (Exception &exception)
- {
- // process the exception (send it to user space)
- process(exception TSRMLS_CC);
- }
- }
- else
- {
- // ArrayAccess is not implemented, is a default handler available?
- if (!std_object_handlers.unset_dimension) return;
-
- // call the default
- std_object_handlers.unset_dimension(object, member TSRMLS_CC);
- }
-}
-
-/**
- * Helper method to turn a property into a zval
- * @param value
- * @param type
- * @return Value
- */
-zval *ClassImpl::toZval(Value &&value, int type)
-{
- // because we do not want the value object to destruct the zval when
- // it falls out of scope, we detach the zval from it, if this is a regular
- // read operation we can do this right away
- if (type == 0) return value.detach();
-
- // this is a more complicated read operation, the scripts wants to get
- // deeper access to the returned value. This, however, is only possible
- // if the value has more than once reference (if it has a refcount of one,
- // the value object that we have here is the only instance of the zval,
- // and it is simply impossible to return a reference or so
- if (value.refcount() <= 1) return value.detach();
-
- // we're dealing with an editable zval, return a reference variable
- return Value(value.detach(), true).detach();
-}
-
-/**
- * Function that is called when a property is read
- * @param object
- * @param name
- * @param type
- * @param key
- * @param tsrm_ls
- * @return val
- */
-#if PHP_VERSION_ID < 50399
-zval *ClassImpl::readProperty(zval *object, zval *name, int type TSRMLS_DC)
-#else
-zval *ClassImpl::readProperty(zval *object, zval *name, int type, const zend_literal *key TSRMLS_DC)
-#endif
-{
- // what to do with the type?
- //
- // the type parameter tells us whether the property was read in READ
- // mode, WRITE mode, READWRITE mode or UNSET mode.
- //
- // In 99 out of 100 situations, it is called in regular READ mode (value 0),
- // only when it is called from a PHP script that has statements like
- // $x =& $object->x, $object->x->y = "something" or unset($object->x->y)
- // the type parameter is set to a different value.
- //
- // But we must ask ourselves the question what we should be doing with such
- // cases. Internally, the object most likely has a full native implementation,
- // and the property that is returned is just a string or integer or some
- // other value, that is temporary WRAPPED into a zval to make it accessible
- // from PHP. If someone wants to get a reference to such an internal variable,
- // that is in most cases simply impossible.
-
- // retrieve the object and class
- 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 = self(entry);
- ClassBase *meta = impl->_base;
-
- // the default implementation throws an exception, so by catching
- // the exception we know if the object was implemented by the user or not
- try
- {
- // convert name to a Value object
- Value key(name);
-
- // is it a property with a callback?
- auto iter = impl->_properties.find(key);
-
- // was it found?
- if (iter == impl->_properties.end())
- {
- // retrieve value from the __get method
- return toZval(meta->callGet(base, key), type);
- }
- else
- {
- // get the value
- return toZval(iter->second->get(base), type);
- }
- }
- catch (const NotImplemented &exception)
- {
- // __get() function was not overridden by the user
- if (!std_object_handlers.read_property) return nullptr;
-
- // call default
-#if PHP_VERSION_ID < 50399
- return std_object_handlers.read_property(object, name, type TSRMLS_CC);
-#else
- return std_object_handlers.read_property(object, name, type, key TSRMLS_CC);
-#endif
- }
- catch (Exception &exception)
- {
- // user threw an exception in its magic method
- // implementation, send it to user space
- process(exception TSRMLS_CC);
-
- // unreachable
- return Value(nullptr).detach();
- }
-}
-
-/**
- * Function that is called when a property is set / updated
- *
- * This is the handler for the __set() function, and is called when a property
- * is 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
- */
-#if PHP_VERSION_ID < 50399
-void ClassImpl::writeProperty(zval *object, zval *name, zval *value TSRMLS_DC)
-#else
-void ClassImpl::writeProperty(zval *object, zval *name, zval *value, const zend_literal *key TSRMLS_DC)
-#endif
-{
- // retrieve the object and class
- 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 = self(entry);
- ClassBase *meta = impl->_base;
-
- // the default implementation throws an exception, if we catch that
- // we know for sure that the user has not overridden the __set method
- try
- {
- // wrap the name
- Value key(name);
-
- // check if the property has a callback
- auto iter = impl->_properties.find(key);
-
- // is it set?
- if (iter == impl->_properties.end())
- {
- // use the __set method
- meta->callSet(base, key, value);
- }
- else
- {
- // check if it could be set
- if (iter->second->set(base, value)) return;
-
- // read-only property
- zend_error(E_ERROR, "Unable to write to read-only property %s", (const char *)key);
- }
- }
- catch (const NotImplemented &exception)
- {
- // __set() function was not overridden by user, check if there is a default
- if (!std_object_handlers.write_property) return;
-
- // call the default
-#if PHP_VERSION_ID < 50399
- std_object_handlers.write_property(object, name, value TSRMLS_CC);
-#else
- std_object_handlers.write_property(object, name, value, key TSRMLS_CC);
-#endif
- }
- catch (Exception &exception)
- {
- // user threw an exception in its magic method
- // implementation, send it to user space
- process(exception TSRMLS_CC);
- }
-}
-
-/**
- * Function that is called to check whether a certain property is set
- * for an object
- *
- * This is the handler for the __isset() function, and is called when a PHP
- * script checks if a certain property is set.
- *
- * The has_set_exists parameter can have the following values:
- *
- * 0 (has) whether property exists and is not NULL
- * 1 (set) whether property exists and is true
- * 2 (exists) whether property exists
- *
- * @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 key ???
- * @param tsrm_ls
- * @return bool
- */
-#if PHP_VERSION_ID < 50399
-int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists TSRMLS_DC)
-#else
-int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists, const zend_literal *key TSRMLS_DC)
-#endif
-{
- // the default implementation throws an exception, if we catch that
- // we know for sure that the user has not overridden the __isset method
- try
- {
- // get the cpp object
- 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 = self(entry);
- ClassBase *meta = impl->_base;
-
- // convert the name to a Value object
- Value key(name);
-
- // check if this is a callback property
- if (impl->_properties.find(key) != impl->_properties.end()) return true;
-
- // call the C++ object
- if (!meta->callIsset(base, key)) return false;
-
- // property exists, but what does the user want to know
- if (has_set_exists == 2) return true;
-
- // we have to retrieve the property
- Value value = meta->callGet(base, key);
-
- // should we check on NULL?
- switch (has_set_exists) {
- case 0: return value.type() != Type::Null;
- default: return value.boolValue();
- }
- }
- catch (const NotImplemented &exception)
- {
- // __isset was not implemented, do we have a default?
- if (!std_object_handlers.has_property) return 0;
-
- // call default
-#if PHP_VERSION_ID < 50399
- return std_object_handlers.has_property(object, name, has_set_exists TSRMLS_CC);
-#else
- return std_object_handlers.has_property(object, name, has_set_exists, key TSRMLS_CC);
-#endif
- }
- catch (Exception &exception)
- {
- // user threw an exception in its magic method
- // implementation, send it to user space
- process(exception TSRMLS_CC);
-
- // unreachable
- return false;
- }
-}
-
-/**
- * Function that is called when a property is removed from the project
- *
- * This is the handler for the __unset() method
- *
- * @param object The object on which it is called
- * @param member The member to remove
- * @param key
- * @param tsrm_ls
- */
-#if PHP_VERSION_ID < 50399
-void ClassImpl::unsetProperty(zval *object, zval *member TSRMLS_DC)
-#else
-void ClassImpl::unsetProperty(zval *object, zval *member, const zend_literal *key TSRMLS_DC)
-#endif
-{
- // the default implementation throws an exception, if we catch that
- // we know for sure that the user has not overridden the __unset method
- try
- {
- // 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 = self(entry);
-
- // property name
- Value name(member);
-
- // is this a callback property?
- 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(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);
- }
- catch (const NotImplemented &exception)
- {
- // __unset was not implemented, do we have a default?
- if (!std_object_handlers.unset_property) return;
-
- // call the default
-#if PHP_VERSION_ID < 50399
- std_object_handlers.unset_property(object, member TSRMLS_CC);
-#else
- std_object_handlers.unset_property(object, member, key TSRMLS_CC);
-#endif
- }
- catch (Exception &exception)
- {
- // user threw an exception in its magic method
- // implementation, send it to user space
- process(exception TSRMLS_CC);
- }
-}
-
-/**
- * Function that is called when an object is about to be destructed
- * This will call the magic __destruct method
- * @param object
- * @param handle
- * @param tsrm_ls
- */
-void ClassImpl::destructObject(zend_object *object, zend_object_handle handle TSRMLS_DC)
-{
- // find object
- ObjectImpl *obj = ObjectImpl::find(object);
-
- // get meta info
- ClassImpl *impl = self(object->ce);
-
- // prevent exceptions
- try
- {
- // call the destruct function
- if (obj->object()) impl->_base->callDestruct(obj->object());
- }
- catch (const NotImplemented &exception)
- {
- // fallback on the default destructor call
- zend_objects_destroy_object(object, handle TSRMLS_CC);
- }
- catch (Exception &exception)
- {
- // a regular Php::Exception was thrown by the extension, pass it on
- // to PHP user space
- process(exception TSRMLS_CC);
- }
-}
-
-/**
- * Function that is called to clean up space that is occupied by the object
- * @param object The object to be deallocated
- * @param tsrm_ls
- */
-void ClassImpl::freeObject(zend_object *object TSRMLS_DC)
-{
- // allocate memory for the object
- ObjectImpl *obj = ObjectImpl::find(object);
-
- // no longer need it
- obj->destruct(TSRMLS_C);
-}
-
-/**
- * Function that is called when an instance of the class needs to be created.
- * This function will create the C++ class, and the PHP object
- * @param entry Pointer to the class information
- * @param tsrm_ls
- * @return zend_object_value The newly created object
- */
-zend_object_value ClassImpl::createObject(zend_class_entry *entry TSRMLS_DC)
-{
- // we need the C++ class meta-information object
- ClassImpl *impl = self(entry);
-
- // create a new base C++ object
- auto *cpp = impl->_base->construct();
-
- // report error on failure
- if (!cpp) throw Php::Exception(std::string("Unable to instantiate ") + entry->name);
-
- // the thing we're going to return
- zend_object_value result;
-
- // set the handlers
- result.handlers = impl->objectHandlers();
-
- // create the object in the zend engine
- ObjectImpl *object = new ObjectImpl(entry, cpp TSRMLS_CC);
-
- // store the object in the object cache
- result.handle = object->handle();
-
- // done
- return result;
-}
-
-/**
- * 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
- */
-zend_object_iterator *ClassImpl::getIterator(zend_class_entry *entry, zval *object, int by_ref TSRMLS_DC)
-{
- // by-ref is not possible (copied from SPL)
- if (by_ref) throw Php::Exception("Foreach by ref is not possible");
-
- // retrieve the traversable object
- Traversable *traversable = dynamic_cast<Traversable*>(ObjectImpl::find(object TSRMLS_CC)->object());
-
- // user may throw an exception in the getIterator() function
- try
- {
- // create an iterator
- auto *iterator = new IteratorImpl(traversable->getIterator());
-
- // return the implementation
- return iterator->implementation();
- }
- catch (Exception &exception)
- {
- // user threw an exception in its method
- // implementation, send it to user space
- process(exception TSRMLS_CC);
-
- // unreachable
- return nullptr;
- }
-}
-
-/**
- * Method that is called to serialize an object
- * @param object The object to be serialized
- * @param buffer Buffer in which to store the data
- * @param buf_len Size of the bufffer
- * @param data ??
- * @param tsrm_ls
- * @return int
- */
-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*>(ObjectImpl::find(object TSRMLS_CC)->object());
-
- // call the serialize method on the object
- auto value = serializable->serialize();
-
- // allocate the buffer, and copy the data into it (the zend engine will
- // (hopefully) clean up the data for us - the default serialize method does
- // it like this too)
- *buffer = (unsigned char*)estrndup(value.c_str(), value.size());
- *buf_len = value.size();
-
- // done
- return SUCCESS;
-}
-
-/**
- * Method that is called to unserialize an object
- * @param object The object to be unserialized
- * @param entry The class entry to which is belongs
- * @param buffer Buffer holding the unserialized data
- * @param data All the unserialize data
- * @param tsrm_ls
- * @return int
- */
-int ClassImpl::unserialize(zval **object, zend_class_entry *entry, const unsigned char *buffer, zend_uint buf_len, zend_unserialize_data *data TSRMLS_DC)
-{
- // create the PHP object
- object_init_ex(*object, entry);
-
- // turn this into a serializale
- Serializable *serializable = dynamic_cast<Serializable*>(ObjectImpl::find(*object TSRMLS_CC)->object());
-
- // call the unserialize method on it
- serializable->unserialize((const char *)buffer, buf_len);
-
- // done
- return SUCCESS;
-}
-
-/**
- * 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 struct _zend_function_entry *ClassImpl::entries()
-{
- // already initialized?
- if (_entries) return _entries;
-
- // allocate memory for the functions
- _entries = new zend_function_entry[_methods.size() + 1];
-
- // keep iterator counter
- int i = 0;
-
- // loop through the functions
- for (auto &method : _methods)
- {
- // retrieve entry
- zend_function_entry *entry = &_entries[i++];
-
- // let the function fill the entry
- method->initialize(entry, _name);
- }
-
- // last entry should be set to all zeros
- zend_function_entry *last = &_entries[i];
-
- // all should be set to zero
- memset(last, 0, sizeof(zend_function_entry));
-
- // done
- return _entries;
-}
-
-/**
- * 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 c++ class object created in the extension
- * @param prefix namespace prefix
- * @param tsrm_ls
- */
-void ClassImpl::initialize(ClassBase *base, const std::string &prefix TSRMLS_DC)
-{
- // store base pointer
- _base = base;
-
- // the class entry
- zend_class_entry entry;
-
- // update the name
- if (prefix.size() > 0) _name = prefix + "\\" + _name;
-
- // initialize the class entry
- INIT_CLASS_ENTRY_EX(entry, _name.c_str(), _name.size(), entries());
-
- // we need a special constructor
- entry.create_object = &ClassImpl::createObject;
-
- // register function that is called for static method calls
- entry.get_static_method = &ClassImpl::getStaticMethod;
-
- // for traversable classes we install a special method to get the iterator
- if (_base->traversable()) entry.get_iterator = &ClassImpl::getIterator;
-
- // for serializable classes, we install callbacks for serializing and unserializing
- if (_base->serializable())
- {
- // add handlers to serialize and unserialize
- entry.serialize = &ClassImpl::serialize;
- entry.unserialize = &ClassImpl::unserialize;
- }
-
- // do we have a base class?
- if (_parent)
- {
- // check if the base class was already defined
- if (_parent->_entry) entry.parent = _parent->_entry;
-
- // otherwise an error is reported
- else std::cerr << "Derived class " << name() << " is initialized before base class " << _parent->name() << ": base class is ignored" << std::endl;
- }
-
- // register the class
- _entry = zend_register_internal_class(&entry TSRMLS_CC);
-
- // register the classes
- for (auto &interface : _interfaces)
- {
- // register this interface
- if (interface->_entry) zend_class_implements(_entry TSRMLS_CC, 1, interface->_entry);
-
- // otherwise report an error
- else std::cerr << "Derived class " << name() << " is initialized before base class " << interface->name() << ": interface is ignored" << std::endl;
- }
-
- // allocate doc comment to contain an empty string + a hidden pointer
- if (!_comment)
- {
- // allocate now
- _comment = (char *)malloc(1 + sizeof(ClassBase *));
-
- // empty string on first position
- _comment[0] = '\0';
-
- // this pointer has to be copied to temporary pointer, as &this causes compiler error
- ClassImpl *impl = this;
-
- // copy the 'this' pointer to the doc-comment
- memcpy(_comment+1, &impl, sizeof(ClassImpl *));
- }
-
- // store pointer to the class in the unused doc_comment member
-#if PHP_VERSION_ID >= 50400
- _entry->info.user.doc_comment = _comment;
-#else
- // and store the wrapper inside the comment
- _entry->doc_comment = _comment;
-#endif
-
- // set access types flags for class
- _entry->ce_flags = (int)_type;
-
- // declare all member variables
- for (auto &member : _members) member->initialize(_entry TSRMLS_CC);
-}
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/classimpl.h b/src/classimpl.h
deleted file mode 100644
index febdbca..0000000
--- a/src/classimpl.h
+++ /dev/null
@@ -1,445 +0,0 @@
-/**
- * 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;
-
- /**
- * Interfaces that are implemented
- * @var std::list
- */
- std::list<std::shared_ptr<ClassImpl>> _interfaces;
-
- /**
- * The parent/base class
- * @var std::shared_ptr
- */
- std::shared_ptr<ClassImpl> _parent;
-
-
- /**
- * 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 class name
- * @return std::string
- */
- const std::string &name() const
- {
- return _name;
- }
-
- /**
- * 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
- */
-#if PHP_VERSION_ID >= 50400
- static zval *readProperty(zval *object, zval *name, int type, const zend_literal *key TSRMLS_DC);
-#else
- static zval *readProperty(zval *object, zval *name, int type TSRMLS_DC);
-#endif
-
- /**
- * 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
- */
-#if PHP_VERSION_ID >= 50400
- static void writeProperty(zval *object, zval *name, zval *value, const zend_literal *key TSRMLS_DC);
-#else
- static void writeProperty(zval *object, zval *name, zval *value TSRMLS_DC);
-#endif
-
- /**
- * 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
- */
-#if PHP_VERSION_ID >= 50400
- static int hasProperty(zval *object, zval *name, int has_set_exists, const zend_literal *key TSRMLS_DC);
-#else
- static int hasProperty(zval *object, zval *name, int has_set_exists TSRMLS_DC);
-#endif
-
- /**
- * 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
- */
-#if PHP_VERSION_ID >= 50400
- static void unsetProperty(zval *object, zval *member, const zend_literal *key TSRMLS_DC);
-#else
- static void unsetProperty(zval *object, zval *member TSRMLS_DC);
-#endif
-
- /**
- * 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
- */
-#if PHP_VERSION_ID >= 50400
- static zend_function *getMethod(zval **object_ptr, char *method, int method_len, const zend_literal *key TSRMLS_DC);
-#else
- static zend_function *getMethod(zval **object_ptr, char *method, int method_len TSRMLS_DC);
-#endif
-
- /**
- * 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 & MethodModifiers, 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 & MethodModifiers, 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 & MethodModifiers, 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 & MethodModifiers, 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 & MethodModifiers, 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 & MethodModifiers, 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 & MethodModifiers, 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 & MethodModifiers, 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 & MethodModifiers) | 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 & MethodModifiers) | 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 & MethodModifiers) | 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 & MethodModifiers) | 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, (flags & (MethodModifiers | Static)) | Abstract , 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 & PropertyModifiers)); }
- void property(const char *name, int16_t value, int flags = Php::Public) { _members.push_back(std::make_shared<NumericMember>(name, value, flags & PropertyModifiers)); }
- void property(const char *name, int32_t value, int flags = Php::Public) { _members.push_back(std::make_shared<NumericMember>(name, value, flags & PropertyModifiers)); }
- void property(const char *name, int64_t value, int flags = Php::Public) { _members.push_back(std::make_shared<NumericMember>(name, value, flags & PropertyModifiers)); }
- void property(const char *name, bool value, int flags = Php::Public) { _members.push_back(std::make_shared<BoolMember> (name, value, flags & PropertyModifiers)); }
- void property(const char *name, char value, int flags = Php::Public) { _members.push_back(std::make_shared<StringMember> (name, &value, 1, flags & PropertyModifiers)); }
- void property(const char *name, const std::string &value, int flags = Php::Public) { _members.push_back(std::make_shared<StringMember> (name, value, flags & PropertyModifiers)); }
- void property(const char *name, const char *value, int flags = Php::Public) { _members.push_back(std::make_shared<StringMember> (name, value, strlen(value), flags & PropertyModifiers)); }
- void property(const char *name, double value, int flags = Php::Public) { _members.push_back(std::make_shared<FloatMember> (name, value, flags & PropertyModifiers)); }
-
- /**
- * 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); }
-
- /**
- * Add an interface that is implemented
- * @param interface The interface that is implemented
- */
- void implements(const std::shared_ptr<ClassImpl> &interface) { _interfaces.push_back(interface); }
-
- /**
- * Set the base class
- * @param base The base class
- */
- void extends(const std::shared_ptr<ClassImpl> &base) { _parent = base; }
-
-};
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/extension.cpp b/src/extension.cpp
deleted file mode 100644
index 9685b32..0000000
--- a/src/extension.cpp
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Extension.cpp
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013, 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Constructor that defines a number of functions right away
- * @param name Extension name
- * @param version Extension version string
- */
-Extension::Extension(const char *name, const char *version) :
- Namespace(""), _impl(new ExtensionImpl(this, name, version)) {}
-
-/**
- * Destructor
- */
-Extension::~Extension()
-{
- // get rid of the implementation object
- delete _impl;
-}
-
-/**
- * Register a function to be called when the PHP engine is ready
- * @param callback
- * @return Extension
- */
-Extension &Extension::onStartup(const Callback &callback)
-{
- // pass on to the implementation
- _impl->onStartup(callback);
-
- // allow chaining
- return *this;
-}
-
-/**
- * Register a function to be called when the PHP engine is going to stop
- * @param callback
- * @return Extension
- */
-Extension &Extension::onShutdown(const Callback &callback)
-{
- // pass on to the implementation
- _impl->onShutdown(callback);
-
- // allow chaining
- return *this;
-}
-
-/**
- * Register a callback that is called at the beginning of each pageview/request
- * @param callback
- */
-Extension &Extension::onRequest(const Callback &callback)
-{
- // pass on to the implementation
- _impl->onRequest(callback);
-
- // allow chaining
- return *this;
-}
-
-/**
- * Register a callback that is called to cleanup things after a pageview/request
- * @param callback
- */
-Extension &Extension::onIdle(const Callback &callback)
-{
- // pass on to the implementation
- _impl->onIdle(callback);
-
- // allow chaining
- return *this;
-}
-
-/**
- * Retrieve the module pointer
- *
- * This is the memory address that should be exported by the get_module()
- * function.
- *
- * @return void*
- */
-void *Extension::module()
-{
- // pass on to the implementation
- return _impl->module();
-}
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/extensionimpl.cpp b/src/extensionimpl.cpp
deleted file mode 100644
index 9562362..0000000
--- a/src/extensionimpl.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/**
- * Extension.cpp
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * If this extension is compiled for a PHP version with multi
- * threading support, we need an additional header file
- */
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-/**
- * We're almost there, we now need to declare an instance of the
- * structure defined above (if building for a single thread) or some
- * sort of impossible to understand magic pointer-to-a-pointer (for
- * multi-threading builds). We make this a static variable because
- * this already is bad enough.
- */
-ZEND_DECLARE_MODULE_GLOBALS(phpcpp)
-
-/**
- * Function that must be defined to initialize the "globals"
- * We do not have to initialize anything, but PHP needs to call this
- * method (crazy)
- * @param globals
- */
-static void init_globals(zend_phpcpp_globals *globals) {}
-
-/**
- * The *startup() and *shutdown() callback functions are passed a module_number
- * variable. However, there does not seem to be a decent API call in Zend to
- * get back the original module_entry linked to this number. So we have to
- * look up entries in a hash table to find the right module entry. To make things
- * even worse, the records in this hash table are copies of the original
- * zend_module_entry structure, so we can also not hide the C++ extension
- * object pointer in the entry that we created ourselves.
- *
- * We have an ugly solution, we keep track of a map of all C++ extension names
- * and their associated extension object, and a map of all module number and
- * the linked extension object.
- *
- * @var map
- */
-static std::map<std::string,ExtensionImpl*> name2extension;
-static std::map<int,ExtensionImpl*> number2extension;
-
-/**
- * Handler function that is used in combination with zend_hash_apply()
- *
- * This function is called when we need to find an extension object based on
- * an extension number. We loop through the list of all registered modules, and
- * for each module we check if we know the extension based on the name
- *
- * @param zend_module_entry
- */
-static int match_module(zend_module_entry *entry)
-{
- // check if there is an extension with this name
- auto iter = name2extension.find(entry->name);
- if (iter == name2extension.end()) return ZEND_HASH_APPLY_KEEP;
-
- // we have the extension, store in combination with the number
- number2extension[entry->module_number] = iter->second;
-
- // done
- return ZEND_HASH_APPLY_KEEP;
-}
-
-/**
- * Find an extension based on the module number
- * @param number
- * @param tsrm_ls
- * @return Extension*
- */
-static ExtensionImpl *find(int number TSRMLS_DC)
-{
- // do we already have an extension with this number?
- auto iter = number2extension.find(number);
- if (iter != number2extension.end()) return iter->second;
-
- // no, not yet, loop through all modules
- zend_hash_apply(&module_registry, (apply_func_t)match_module TSRMLS_CC);
-
- // find again
- iter = number2extension.find(number);
- if (iter == number2extension.end()) return nullptr;
-
- // found!
- return iter->second;
-}
-
-/**
- * Function that is called when the extension initializes
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int 0 on success
- */
-int ExtensionImpl::onStartup(int type, int module_number TSRMLS_DC)
-{
- // initialize and allocate the "global" variables
- ZEND_INIT_MODULE_GLOBALS(phpcpp, init_globals, NULL);
-
- // get the extension
- auto *extension = find(module_number TSRMLS_CC);
-
- // initialize the extension
- extension->initialize(TSRMLS_C);
-
- // is the callback registered?
- if (extension->_onStartup) extension->_onStartup();
-
- // done
- return BOOL2SUCCESS(true);
-}
-
-/**
- * Function that is called when the extension is about to be stopped
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int
- */
-int ExtensionImpl::onShutdown(int type, int module_number TSRMLS_DC)
-{
- // get the extension
- auto *extension = find(module_number TSRMLS_CC);
-
- // is the callback registered?
- if (extension->_onShutdown) extension->_onShutdown();
-
- // done
- return BOOL2SUCCESS(true);
-}
-
-/**
- * Function that is called when a request starts
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int 0 on success
- */
-int ExtensionImpl::onRequest(int type, int module_number TSRMLS_DC)
-{
- // get the extension
- auto *extension = find(module_number TSRMLS_CC);
-
- // is the callback registered?
- if (extension->_onRequest) extension->_onRequest();
-
- // done
- return BOOL2SUCCESS(true);
-}
-
-/**
- * Function that is called when a request is ended
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int 0 on success
- */
-int ExtensionImpl::onIdle(int type, int module_number TSRMLS_DC)
-{
- // get the extension
- auto *extension = find(module_number TSRMLS_CC);
-
- // is the callback registered?
- if (extension->_onIdle) extension->_onIdle();
-
- // done
- return BOOL2SUCCESS(true);
-}
-
-/**
- * Constructor
- * @param data Pointer to the extension object created by the extension programmer
- * @param name Name of the extension
- * @param version Version number
- */
-ExtensionImpl::ExtensionImpl(Extension *data, const char *name, const char *version) : _data(data)
-{
- // keep extension pointer based on the name
- name2extension[name] = this;
-
- // assign all members (apart from the globals)
- _entry.size = sizeof(zend_module_entry); // size of the data
- _entry.zend_api = ZEND_MODULE_API_NO; // api number
- _entry.zend_debug = ZEND_DEBUG; // debug mode enabled?
- _entry.zts = USING_ZTS; // is thread safety enabled?
- _entry.ini_entry = NULL; // the php.ini record
- _entry.deps = NULL; // dependencies on other modules
- _entry.name = name; // extension name
- _entry.functions = NULL; // functions supported by this module (none for now)
- _entry.module_startup_func = &ExtensionImpl::onStartup; // startup function for the whole extension
- _entry.module_shutdown_func = &ExtensionImpl::onShutdown; // shutdown function for the whole extension
- _entry.request_startup_func = &ExtensionImpl::onRequest; // startup function per request
- _entry.request_shutdown_func = &ExtensionImpl::onIdle; // shutdown function per request
- _entry.info_func = NULL; // information for retrieving info
- _entry.version = version; // version string
- _entry.globals_size = 0; // size of the global variables
- _entry.globals_ctor = NULL; // constructor for global variables
- _entry.globals_dtor = NULL; // destructor for global variables
- _entry.post_deactivate_func = NULL; // unknown function
- _entry.module_started = 0; // module is not yet started
- _entry.type = 0; // temporary or persistent module, will be filled by Zend engine
- _entry.handle = NULL; // dlopen() handle, will be filled by Zend engine
- _entry.module_number = 0; // module number will be filled in by Zend engine
- _entry.build_id = (char *)ZEND_MODULE_BUILD_ID; // check if extension and zend engine are compatible
-
- // things that only need to be initialized
-#ifdef ZTS
- _entry.globals_id_ptr = NULL;
-#else
- _entry.globals_ptr = NULL;
-#endif
-
-}
-
-/**
- * Destructor
- */
-ExtensionImpl::~ExtensionImpl()
-{
- // deallocate functions
- if (_entry.functions) delete[] _entry.functions;
-}
-
-/**
- * Retrieve the module entry
- * @return zend_module_entry
- */
-zend_module_entry *ExtensionImpl::module()
-{
- // check if functions we're already defined
- if (_entry.functions) return &_entry;
-
- // the number of functions
- int count = _data->functions();
-
- // skip if there are no functions
- if (count == 0) return &_entry;
-
- // allocate memory for the functions
- zend_function_entry *entries = new zend_function_entry[count + 1];
-
- // index being processed
- int i = 0;
-
- // apply a function to each function
- _data->apply([&i, entries](const std::string &prefix, Function &function) {
-
- // initialize the function
- function.initialize(prefix, &entries[i]);
-
- // move on to the next iteration
- i++;
- });
-
- // last entry should be set to all zeros
- zend_function_entry *last = &entries[count];
-
- // all should be set to zero
- memset(last, 0, sizeof(zend_function_entry));
-
- // store functions in entry object
- _entry.functions = entries;
-
- // return the entry
- return &_entry;
-}
-
-/**
- * Initialize the extension after it was started
- * @param tsrm_ls
- */
-void ExtensionImpl::initialize(TSRMLS_D)
-{
- // we need to register each class, find out all classes
- _data->apply([TSRMLS_C](const std::string &prefix, ClassBase &c) {
-
- // forward to implementation class
- c.implementation()->initialize(&c, prefix TSRMLS_CC);
- });
-}
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/extensionimpl.h b/src/extensionimpl.h
deleted file mode 100644
index cc37354..0000000
--- a/src/extensionimpl.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * ExtensionImpl.h
- *
- * Extension implementation for the Zend engine.
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013, 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class ExtensionImpl
-{
-protected:
- /**
- * Pointer to the extension object that is filled by the extension programmer
- * @var Extension
- */
- Extension *_data;
-
- /**
- * The information that is passed to the Zend engine
- *
- * Although it would be slightly faster to not make this a pointer, this
- * would require that client code also includes the PHP header files, which
- * we try to prevent with the PHP-CPP library, so we allocate it dynamically.
- *
- * @var zend_module_entry
- */
- zend_module_entry _entry;
-
- /**
- * Callback that is called after the engine is initialized and before the
- * pageviews are going to be handled
- * @var Callback
- */
- Callback _onStartup;
-
- /**
- * Callback that is called in front of each request
- * @var Callback
- */
- Callback _onRequest;
-
- /**
- * Callback that is called right after each request
- * @var Callback
- */
- Callback _onIdle;
-
- /**
- * Callback that is called right before the engine is closing down
- * @var Callback
- */
- Callback _onShutdown;
-
-public:
- /**
- * Constructor
- * @param data Extension object created by the extension programmer
- * @param name Name of the extension
- * @param version Version number
- */
- ExtensionImpl(Extension *data, const char *name, const char *version);
-
- /**
- * No copy'ing and no moving
- */
- ExtensionImpl(const ExtensionImpl &extension) = delete;
- ExtensionImpl(ExtensionImpl &&extension) = delete;
-
- /**
- * Destructor
- */
- virtual ~ExtensionImpl();
-
- /**
- * Register a function to be called when the PHP engine is ready
- *
- * The callback will be called after all extensions are loaded, and all
- * functions and classes are available, but before the first pageview/request
- * is handled. You can register this callback if you want to be notified
- * when the engine is ready, for example to initialize certain things.
- *
- * @param callback
- */
- void onStartup(const Callback &callback)
- {
- // copy callback
- _onStartup = callback;
- }
-
- /**
- * Register a function to be called when the PHP engine is going to stop
- *
- * The callback will be called right before the process is going to stop.
- * You can register a function if you want to clean up certain things.
- *
- * @param callback
- */
- void onShutdown(const Callback &callback)
- {
- // copy callback
- _onShutdown = callback;
- }
-
- /**
- * Register a callback that is called at the beginning of each pageview/request
- *
- * You can register a callback if you want to initialize certain things
- * at the beginning of each request. Remember that the extension can handle
- * multiple requests after each other, and you may want to set back certain
- * global variables to their initial variables in front of each request
- *
- * @param callback
- */
- void onRequest(const Callback &callback)
- {
- // copy callback
- _onRequest = callback;
- }
-
- /**
- * Register a callback that is called to cleanup things after a pageview/request
- *
- * The callback will be called after _each_ request, so that you can clean up
- * certain things and make your extension ready to handle the next request.
- * This method is called onIdle because the extension is idle in between
- * requests.
- *
- * @param callback
- */
- void onIdle(const Callback &callback)
- {
- // copy callback
- _onIdle = callback;
- }
-
- /**
- * Retrieve the module entry
- *
- * This is the memory address that should be exported by the get_module()
- * function.
- *
- * @return _zend_module_entry
- */
- zend_module_entry *module();
-
- /**
- * Cast to a module entry
- * @return _zend_module_entry*
- */
- operator zend_module_entry * ()
- {
- return module();
- }
-
-private:
- /**
- * Initialize the namespace after it was registered
- * @param tsrm_ls
- */
- void initialize(TSRMLS_D);
-
- /**
- * Function that is called when the extension initializes
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int 0 on success
- */
- static int onStartup(int type, int module_number TSRMLS_DC);
-
- /**
- * Function that is called when the extension is about to be stopped
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int
- */
- static int onShutdown(int type, int module_number TSRMLS_DC);
-
- /**
- * Function that is called when a request starts
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int 0 on success
- */
- static int onRequest(int type, int module_number TSRMLS_DC);
-
- /**
- * Function that is called when a request is ended
- * @param type Module type
- * @param number Module number
- * @param tsrm_ls
- * @return int 0 on success
- */
- static int onIdle(int type, int module_number TSRMLS_DC);
-};
-
-/**
- * End of namespace
- */
-}
-
-
diff --git a/src/floatmember.h b/src/floatmember.h
deleted file mode 100644
index 9b5d4f2..0000000
--- a/src/floatmember.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * FloatMember.h
- *
- * Implementation for a property that is initially set to a boolean value
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013, 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class FloatMember : public Member
-{
-private:
- /**
- * The value
- * @var double
- */
- double _value;
-
-public:
- /**
- * Constructor
- * @param name
- * @param value
- * @param flags
- */
- FloatMember(const char *name, double value, int flags) : Member(name, flags), _value(value) {}
-
- /**
- * Destructor
- */
- virtual ~FloatMember() {}
-
- /**
- * Virtual method to declare class constant
- * @param entry Class entry
- * @param tsrm_ls
- */
- virtual void constant(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- zend_declare_class_constant_double(entry, _name.c_str(), _name.size(), _value TSRMLS_CC);
- }
-
- /**
- * Virtual method to declare the property
- * @param entry Class entry'
- * @param tsrm_ls
- */
- virtual void declare(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- // converstion to char* necessary for php 5.3
- zend_declare_property_double(entry, (char *)_name.c_str(), _name.size(), _value, _flags TSRMLS_CC);
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/function.h b/src/function.h
deleted file mode 100644
index 4c34ac7..0000000
--- a/src/function.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Function.h
- *
- * The Function class is an extension of the Callable class that
- * forwards the function call directly to a native function in C/C++
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class Function : public Callable
-{
-public:
- /**
- * Constructor
- * @param name Function name
- * @param function The native C function
- */
- Function(const char *name, const native_callback_0 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(0) { _function.f0 = function; }
- Function(const char *name, const native_callback_1 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(1) { _function.f1 = function; }
- Function(const char *name, const native_callback_2 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(2) { _function.f2 = function; }
- Function(const char *name, const native_callback_3 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(3) { _function.f3 = function; }
-
- /**
- * Copy constructor
- * @param that
- */
- Function(const Function &that) : Callable(that), _function(that._function), _type(that._type) {}
-
- /**
- * Move constructor
- * @param that
- */
- Function(Function &&that) : Callable(std::move(that)), _function(that._function), _type(that._type) {}
-
- /**
- * Destructor
- */
- virtual ~Function() {}
-
- /**
- * Method that gets called every time the function is executed
- * @param params The parameters that were passed
- * @return Variable Return value
- */
- virtual Value invoke(Parameters &params) override
- {
- switch (_type) {
- case 0: _function.f0(); return Value();
- case 1: _function.f1(params); return Value();
- case 2: return _function.f2();
- case 3: return _function.f3(params);
- default: return Value();
- }
- }
-
- /**
- * Fill a function entry
- * @param prefix Active namespace prefix
- * @param entry Entry to be filled
- */
- void initialize(const std::string &prefix, zend_function_entry *entry)
- {
- // if there is a namespace prefix, we should adjust the name
- if (prefix.size()) _ptr = HiddenPointer<Callable>(this, prefix+"\\"+(const char *)_ptr);
-
- // call base initialize
- Callable::initialize(entry);
- }
-
-private:
- /**
- * Union of supported callbacks
- * One of the callbacks will be set
- */
- union {
- native_callback_0 f0;
- native_callback_1 f1;
- native_callback_2 f2;
- native_callback_3 f3;
- } _function;
-
- /**
- * The callback that is set
- * @var integer
- */
- int _type;
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/global.cpp b/src/global.cpp
deleted file mode 100644
index 7eea8e7..0000000
--- a/src/global.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * Global.cpp
- *
- * Implementation for the global variable
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Namespace
- */
-namespace Php {
-
-/**
- * Function that is called when the value is updated
- * @return Value
- */
-Global &Global::update()
-{
- // skip if the variable already exists
- if (_exists) return *this;
-
- // we need the TSRMLS variable
- TSRMLS_FETCH();
-
- // add the variable to the globals
- zend_hash_add(EG(active_symbol_table), _name.c_str(), _name.size()+1, &_val, sizeof(zval*), NULL);
-
- // add one extra reference because the variable now is a global var too
- Z_ADDREF_P(_val);
-
- // remember that the variable now exists
- _exists = true;
-
- // done
- return *this;
-}
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/globals.cpp b/src/globals.cpp
deleted file mode 100644
index 8132ef3..0000000
--- a/src/globals.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * Globals.cpp
- *
- * Implementation of the globals class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Namespace
- */
-namespace Php {
-
-/**
- * Get access to the globals single instance
- * @return Globals
- */
-Globals &Globals::instance()
-{
- static Globals globals;
- return globals;
-}
-
-/**
- * The one and only instance
- * @var Globals
- */
-Globals &GLOBALS = Globals::instance();
-
-/**
- * Get access to a global variable
- * @param name
- * @return Global
- */
-Global Globals::operator[](const char *name)
-{
- // pointer to a zval
- zval **varvalue;
-
- // we need the TSRMLS variable
- TSRMLS_FETCH();
-
- // check if the variable already exists
- if (zend_hash_find(&EG(symbol_table), name, strlen(name)+1, (void**)&varvalue) == FAILURE)
- {
- // the variable does not already exist, return a global object
- // that will automatically set the value when it is updated
- return Global(name);
- }
- else
- {
- // we are in the happy situation that the variable exists, we turn
- // this value into a reference value, and return that
- return Global(name, *varvalue);
- }
-}
-
-/**
- * Get access to a global variable
- * @param name
- * @return Global
- */
-Global Globals::operator[](const std::string &name)
-{
- // pointer to a zval
- zval **varvalue;
-
- // we need the TSRMLS variable
- TSRMLS_FETCH();
-
- // check if the variable already exists
- if (zend_hash_find(&EG(symbol_table), name.c_str(), name.size()+1, (void**)&varvalue) == FAILURE)
- {
- // the variable does not already exist, return a global object
- // that will automatically set the value when it is updated
- return Global(name);
- }
- else
- {
- // we are in the happy situation that the variable exists, we turn
- // this value into a reference value, and return that
- return Global(name, *varvalue);
- }
-}
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/hashiterator.h b/src/hashiterator.h
deleted file mode 100644
index b1f409f..0000000
--- a/src/hashiterator.h
+++ /dev/null
@@ -1,250 +0,0 @@
-/**
- * HashIterator.h
- *
- * This is an internal helper class that is used when iterating over a
- * Php::Value object that holds a hash table (an array or an object that
- * does not implement the Traversable interface - stl style.
- *
- * Thus, when you do c++ things like "for (auto &iter : value)", internally
- * a ValueIterator object is being used.
- *
- * @author Emiel Bruijntjes
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class HashIterator : public ValueIteratorImpl
-{
-public:
- /**
- * Constructor
- * @param hashtable The hashtable to iterate over
- * @param first Should it start on the first position?
- * @param tsrm_ls
- */
- HashIterator(HashTable *hashtable, bool first) : _table(hashtable)
- {
- // reset the hash pointer to the internal position
- if (hashtable && first)
- {
- // move to first position
- zend_hash_internal_pointer_reset_ex(_table, &_position);
-
- // read current data
- if (read()) return;
-
- // data was private, move on
- increment();
- }
- else
- {
- // start with invalid data
- invalidate();
- }
- }
-
- /**
- * Copy constructor
- * @param that
- * @param tsrm_ls
- */
- HashIterator(const HashIterator &that TSRMLS_DC) :
- _table(that._table), _position(that._position)
- {
- // read current position
- read();
- }
-
- /**
- * Destructor
- */
- virtual ~HashIterator() {}
-
- /**
- * Clone the object
- * @param tsrm_ls
- * @return ValueIteratorImpl
- */
- virtual ValueIteratorImpl *clone()
- {
- // create a new instance
- return new HashIterator(*this);
- }
-
- /**
- * Increment position (pre-increment)
- * @return bool
- */
- virtual bool increment() override
- {
- // leap out if already on an invalid pos (behind the last pos)
- if (!_position) return false;
-
- // move the iterator forward
- if (zend_hash_move_forward_ex(_table, &_position) == SUCCESS)
- {
- // read current key and value
- if (read()) return true;
-
- // data was private or invalid, move further
- return increment();
- }
- else
- {
- // invalidate current position
- return invalidate();
- }
- }
-
- /**
- * Decrement position (pre-decrement)
- * @return bool
- */
- virtual bool decrement() override
- {
- // leap out if we're not even iterating over a hash table
- if (!_table) return false;
-
- // if position is invalid, it is one position behind the last position
- if (!_position)
- {
- // move to last position
- zend_hash_internal_pointer_end_ex(_table, &_position);
- }
- else if (zend_hash_move_backwards_ex(_table, &_position) == FAILURE)
- {
- // invalidate current position
- return invalidate();
- }
-
- // read current key and value
- if (read()) return true;
-
- // data was private, move on
- return decrement();
- }
-
- /**
- * Compare with other iterator
- * @param that
- * @return bool
- */
- virtual bool equals(const ValueIteratorImpl *that) const override
- {
- // this always is a hash iterator
- HashIterator *other = (HashIterator *)that;
-
- // compare the positions
- return _position == other->_position;
- }
-
- /**
- * Derefecence, this returns a std::pair with the current key and value
- * @return std::pair
- */
- virtual const std::pair<Value,Value> &current() const override
- {
- return _current;
- }
-
-private:
- /**
- * The hash table over which is being iterated
- * @var HashTable
- */
- HashTable *_table = nullptr;
-
- /**
- * The position in the hash table
- * @var HashPosition
- */
- Bucket *_position = nullptr;
-
- /**
- * The current key and value
- * @var std::pair
- */
- std::pair<Value,Value> _current;
-
- /**
- * Read current key and value
- * @return bool
- */
- bool read()
- {
- // zval to read the current key in
- Value key;
-
-#if PHP_VERSION_ID >= 50500
-
- // read in the current key
- zend_hash_get_current_key_zval_ex(_table, key._val, &_position);
-
- // if the key is set to NULL, it means that the object is not at a valid position
- if (key.isNull()) return invalidate();
-
-#else
-
- // php 5.3 and php 5.4 need a different implementation because the function
- // zend_hash_get_current_key_zval_ex is missing in php 5.3, declare variables
- // we need for storing the key in
- char *string_key;
- unsigned int str_len;
- unsigned long num_key;
-
- // get the current key
- int type = zend_hash_get_current_key_ex(_table, &string_key, &str_len, &num_key, 0, &_position);
-
- // if key is not found, the iterator is at an invalid position
- if (type == HASH_KEY_NON_EXISTANT) return invalidate();
-
- // numeric keys are the easiest ones
- if (type == HASH_KEY_IS_LONG) key = (int64_t)num_key;
- else key = string_key;
-
-#endif
-
- // iterator is at a valid position, go fetch the data
- // this is the variable we need for fetching the data
- zval **value;
-
- // retrieve data
- zend_hash_get_current_data_ex(_table, (void **) &value, &_position);
-
- // we can now update the current data
- _current = std::make_pair<Value,Value>(std::move(key), *value);
-
- // if the key is private (it starts with a null character) we should return
- // false to report that the object is not in a completely valid state
- return !_current.first.isString() || _current.first.rawValue()[0];
- }
-
- /**
- * Invalidate the iterator
- * @return bool
- */
- bool invalidate()
- {
- // forget current position
- _position = nullptr;
-
- // make the data a pair of null ptrs
- _current = std::make_pair<Value,Value>(nullptr,nullptr);
-
- // done
- return false;
- }
-};
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/hashmember.cpp b/src/hashmember.cpp
deleted file mode 100644
index f6f8483..0000000
--- a/src/hashmember.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * HashMember.cpp
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Custom output stream operator
- * @param stream
- * @param value
- * @return ostream
- */
-std::ostream &operator<<(std::ostream &stream, const HashMember<int> &value)
-{
- return stream << value.value();
-}
-
-/**
- * Custom output stream operator
- * @param stream
- * @param value
- * @return ostream
- */
-std::ostream &operator<<(std::ostream &stream, const HashMember<std::string> &value)
-{
- return stream << value.value();
-}
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/includes.h b/src/includes.h
deleted file mode 100644
index 0019244..0000000
--- a/src/includes.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * Includes.h
- *
- * Startup include file to compile the phpcpp library
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Include standard C and C++ libraries
- */
-#include <stdlib.h>
-#include <string>
-#include <initializer_list>
-#include <vector>
-#include <map>
-#include <memory>
-#include <list>
-#include <exception>
-#include <type_traits>
-
-// for debug
-#include <iostream>
-
-#define ZTS
-#define THREAD_T pthread_t
-#define MUTEX_T pthread_mutex_t *
-
-/**
- * PHP includes
- */
-#pragma GCC system_header
-#include <php.h>
-#include <zend_exceptions.h>
-#include <zend_interfaces.h>
-
-/**
- * Macro to convert results to success status
- */
-#define BOOL2SUCCESS(b) ((b) ? SUCCESS : FAILURE)
-
-/**
- * Include other files from this library
- */
-#include "../include/exception.h"
-#include "../include/streams.h"
-#include "../include/type.h"
-#include "../include/hashparent.h"
-#include "../include/value.h"
-#include "../include/valueiterator.h"
-#include "../include/array.h"
-#include "../include/object.h"
-#include "../include/hiddenpointer.h"
-#include "../include/globals.h"
-#include "../include/argument.h"
-#include "../include/byval.h"
-#include "../include/byref.h"
-#include "../include/global.h"
-#include "../include/super.h"
-#include "../include/hashmember.h"
-#include "../include/parameters.h"
-#include "../include/modifiers.h"
-#include "../include/base.h"
-#include "../include/countable.h"
-#include "../include/arrayaccess.h"
-#include "../include/serializable.h"
-#include "../include/iterator.h"
-#include "../include/traversable.h"
-#include "../include/classtype.h"
-#include "../include/classbase.h"
-#include "../include/interface.h"
-#include "../include/class.h"
-#include "../include/namespace.h"
-#include "../include/extension.h"
-#include "../include/call.h"
-
-/**
- * Interface files for internal use only
- */
-#include "init.h"
-#include "callable.h"
-#include "function.h"
-#include "method.h"
-#include "member.h"
-#include "nullmember.h"
-#include "numericmember.h"
-#include "boolmember.h"
-#include "stringmember.h"
-#include "floatmember.h"
-#include "arithmetic.h"
-#include "origexception.h"
-#include "notimplemented.h"
-#include "property.h"
-#include "valueiteratorimpl.h"
-#include "hashiterator.h"
-#include "invaliditerator.h"
-#include "traverseiterator.h"
-#include "iteratorimpl.h"
-#include "streambuf.h"
-#include "classimpl.h"
-#include "objectimpl.h"
-#include "parametersimpl.h"
-#include "extensionimpl.h"
-
-#ifndef ZVAL_COPY_VALUE
-#define ZVAL_COPY_VALUE(z, v) \
- do { \
- (z)->value = (v)->value; \
- Z_TYPE_P(z) = Z_TYPE_P(v); \
- } while (0)
-#endif
-
-#ifndef INIT_PZVAL_COPY
-#define INIT_PZVAL_COPY(z, v) \
- do { \
- ZVAL_COPY_VALUE(z, v); \
- Z_SET_REFCOUNT_P(z, 1); \
- Z_UNSET_ISREF_P(z); \
- } while (0)
-#endif
diff --git a/src/init.h b/src/init.h
deleted file mode 100644
index 8f914f5..0000000
--- a/src/init.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * Init.h
- *
- * Variables and structured required by the Zend engine to work
- * with global variables
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Namespace
- */
-namespace Php {
-
-/**
- * The way how PHP C API deals with "global" variables is peculiar.
- *
- * The following macros are supposed to turn into a structure that is going
- * to be instantiated for each parallel running request, and for which the
- * PHP engine allocates a certain amount of memory, and a magic pointer that
- * is passed and should be forwarded to every thinkable PHP function.
- *
- * We don't use this architecture. We have our own environment object
- * that makes much more sense, and that we use. However, the Zend engine
- * expects this structure and this structure to exist.
- */
-ZEND_BEGIN_MODULE_GLOBALS(phpcpp)
-ZEND_END_MODULE_GLOBALS(phpcpp)
-
-/**
- * And now we're going to define a macro. This also is a uncommon architecture
- * from PHP to get access to a variable from the structure above.
- */
-#ifdef ZTS
-#define PHPCPP_G(v) TSRMG(phpcpp_globals_id, phpcpp_globals *, v)
-#else
-#define PHPCPP_G(v) (phpcpp_globals.v)
-#endif
-
-/**
- * We're almost there, we now need to declare an instance of the
- * structure defined above (if building for a single thread) or some
- * sort of impossible to understand magic pointer-to-a-pointer (for
- * multi-threading builds). We make this a static variable because
- * this already is bad enough.
- */
-extern ZEND_DECLARE_MODULE_GLOBALS(phpcpp)
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/invaliditerator.h b/src/invaliditerator.h
deleted file mode 100644
index 388eca8..0000000
--- a/src/invaliditerator.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * InvalidIterator.h
- *
- * Iterator class that is used for value objects that are not even
- * iteratable.
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class InvalidIterator : public ValueIteratorImpl
-{
-public:
- /**
- * Clone the object
- * @param tsrm_ls
- * @return ValueIteratorImpl
- */
- virtual ValueIteratorImpl *clone()
- {
- // create a new instance
- return new InvalidIterator(*this);
- }
-
- /**
- * Increment position (pre-increment)
- * @param tsrm_ls
- * @return bool
- */
- virtual bool increment() override
- {
- return false;
- }
-
- /**
- * Decrement position (pre-decrement)
- * @return bool
- */
- virtual bool decrement() override
- {
- return false;
- }
-
- /**
- * Compare with other iterator
- * @param that
- * @return bool
- */
- virtual bool equals(const ValueIteratorImpl *that) const override
- {
- // the other iterator is also an invalid-iterator, and all invalid
- // iterators are equal
- return true;
- }
-
- /**
- * Derefecence, this returns a std::pair with the current key and value
- * @return std::pair
- */
- virtual const std::pair<Value,Value> &current() const override
- {
- // this method is never called, when it is, we create a static instance
- static std::pair<Value,Value> result;
-
- // return it
- return result;
- }
-};
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/iteratorimpl.cpp b/src/iteratorimpl.cpp
deleted file mode 100644
index 2750ddb..0000000
--- a/src/iteratorimpl.cpp
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * IteratorImpl.cpp
- *
- * Implementation file of the IteratorImpl class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Helper method to get access to ourselves
- * @param iter
- * @return IteratorImpl
- */
-static IteratorImpl *self(zend_object_iterator *iter)
-{
- return (IteratorImpl *)iter->data;
-}
-
-/**
- * Iterator destructor method
- * @param iter
- * @param tsrm_ls
- */
-void IteratorImpl::destructor(zend_object_iterator *iter TSRMLS_DC)
-{
- // delete the object
- delete self(iter);
-}
-
-/**
- * Iterator valid function
- * Returns FAILURE or SUCCESS
- * @param iter
- * @param tsrm_ls
- * @return int
- */
-int IteratorImpl::valid(zend_object_iterator *iter TSRMLS_DC)
-{
- // check if valid
- return self(iter)->valid() ? SUCCESS : FAILURE;
-}
-
-/**
- * Fetch the current item
- * @param iter
- * @param data
- * @param tsrm_ls
- */
-void IteratorImpl::current(zend_object_iterator *iter, zval ***data TSRMLS_DC)
-{
- // get the actual iterator
- IteratorImpl *iterator = self(iter);
-
- // retrieve the value (and store it in a member so that it is not
- // destructed when the function returns)
- iterator->_current = iterator->current();
-
- // copy the value
- *data = &iterator->_current._val;
-}
-
-/**
- * Fetch the key for the current element (optional, may be NULL). The key
- * should be written into the provided zval* using the ZVAL_* macros. If
- * this handler is not provided auto-incrementing integer keys will be
- * used.
- * @param iter
- * @param key
- * @param tsrm_ls
- */
-void IteratorImpl::key(zend_object_iterator *iter, zval *key TSRMLS_DC)
-{
- // retrieve the key
- Value retval(self(iter)->key());
-
- // detach the underlying zval
- zval *val = retval.detach();
-
- // copy it to the key
- ZVAL_ZVAL(key, val, 1, 1);
-}
-
-/**
- * Function to retrieve the current key, php 5.3 style
- * @param iter
- * @param str_key
- * @param str_key_len
- * @param int_key
- * @param tsrm_ls
- * @return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG
- */
-int IteratorImpl::key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC)
-{
- // retrieve the key
- Value retval(self(iter)->key());
-
- // is this a numeric string?
- if (retval.isString())
- {
- // copy the key and the from the value
- *str_key = estrndup(retval.rawValue(), retval.size());
- *str_key_len = retval.size() + 1;
-
- // done
- return HASH_KEY_IS_STRING;
- }
- else
- {
- // convert to a numeric
- *int_key = retval.numericValue();
-
- // done
- return HASH_KEY_IS_LONG;
- }
-}
-
-/**
- * Step forwards to the next element
- * @param iter
- * @param tsrm_ls
- */
-void IteratorImpl::next(zend_object_iterator *iter TSRMLS_DC)
-{
- // call the next method
- self(iter)->next();
-}
-
-/**
- * Rewind the iterator back to the start
- * @param iter
- * @param tsrm_ls
- */
-void IteratorImpl::rewind(zend_object_iterator *iter TSRMLS_DC)
-{
- // call the rewind method
- self(iter)->rewind();
-}
-
-/**
- * Get access to all iterator functions
- * @return zend_object_iterator_funcs
- */
-zend_object_iterator_funcs *IteratorImpl::functions()
-{
- // static variable with all functions
- static zend_object_iterator_funcs funcs;
-
- // static variable that knows if the funcs are already initialized
- static bool initialized = false;
-
- // no need to set anything if already initialized
- if (initialized) return &funcs;
-
- // set the members
- funcs.dtor = &IteratorImpl::destructor;
- funcs.valid = &IteratorImpl::valid;
- funcs.get_current_data = &IteratorImpl::current;
- funcs.get_current_key = &IteratorImpl::key;
- funcs.move_forward = &IteratorImpl::next;
- funcs.rewind = &IteratorImpl::rewind;
-
- // invalidate is not yet supported
- funcs.invalidate_current = nullptr;
-
- // remember that functions are initialized
- initialized = true;
-
- // done
- return &funcs;
-}
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/iteratorimpl.h b/src/iteratorimpl.h
deleted file mode 100644
index 0a815e2..0000000
--- a/src/iteratorimpl.h
+++ /dev/null
@@ -1,190 +0,0 @@
-/**
- * Iterator.h
- *
- * Base class for iterators. Extension writers that want to create traversable
- * classes, should override the Php::Traversable base class. This base class
- * forces you to implement a getIterator() method that returns an instance of
- * a Php::Iterator class.
- *
- * In this file you find the signature of the Php::Iterator class. It mostly has
- * pure virtual methods, which means that you should create a derived class
- * that implements all these methods.
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class IteratorImpl
-{
-private:
- /**
- * Unique pointer to the iterator that is returned by the extension
- * @var std::unique_ptr
- */
- std::unique_ptr<Iterator> _iterator;
-
- /**
- * The current() method that is called by the Zend engine wants a
- * pointer-to-pointer-to-a-zval. Because of this, we have to keep the
- * current value in memory after the current() method returns because
- * the pointer would otherwise fall out of scope. This is (once again)
- * odd behavior of the Zend engine, but we'll have to live with that
- * @var Value
- */
- Value _current;
-
- /**
- * The object iterator as is needed by the Zend engine
- * @var zend_object_iterator
- */
- zend_object_iterator _impl;
-
- /**
- * Get access to all iterator functions
- * @return zend_object_iterator_funcs
- */
- static zend_object_iterator_funcs *functions();
-
- /**
- * Is the iterator on a valid position
- * @return bool
- */
- bool valid()
- {
- return _iterator->valid();
- }
-
- /**
- * The value at the current position
- * @return Value
- */
- Value current()
- {
- return _iterator->current();
- }
-
- /**
- * The key at the current position
- * @return Value
- */
- Value key()
- {
- return _iterator->key();
- }
-
- /**
- * Move to the next position
- */
- void next()
- {
- return _iterator->next();
- }
-
- /**
- * Rewind the iterator to the front position
- */
- void rewind()
- {
- return _iterator->rewind();
- }
-
- /**
- * Iterator destructor method
- * @param iter
- * @param tsrm_ls
- */
- static void destructor(zend_object_iterator *iter TSRMLS_DC);
-
- /**
- * Iterator valid function
- * Returns FAILURE or SUCCESS
- * @param iter
- * @param tsrm_ls
- * @return int
- */
- static int valid(zend_object_iterator *iter TSRMLS_DC);
-
- /**
- * Fetch the current item
- * @param iter
- * @param data
- * @param tsrm_ls
- */
- static void current(zend_object_iterator *iter, zval ***data TSRMLS_DC);
-
- /**
- * Fetch the key for the current element (optional, may be NULL). The key
- * should be written into the provided zval* using the ZVAL_* macros. If
- * this handler is not provided auto-incrementing integer keys will be
- * used.
- * @param iter
- * @param data
- * @param tsrm_ls
- */
- static void key(zend_object_iterator *iter, zval *data TSRMLS_DC);
-
- /**
- * Function to retrieve the current key, php 5.3 style
- * @param iter
- * @param str_key
- * @param str_key_len
- * @param int_key
- * @param tsrm_ls
- * @return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG
- */
- static int key(zend_object_iterator *iter, char **str_key, unsigned int *str_key_len, unsigned long *int_key TSRMLS_DC);
-
- /**
- * Step forwards to the next element
- * @param iter
- * @param tsrm_ls
- */
- static void next(zend_object_iterator *iter TSRMLS_DC);
-
- /**
- * Rewind the iterator back to the start
- * @param iter
- * @param tsrm_ls
- */
- static void rewind(zend_object_iterator *iter TSRMLS_DC);
-
-public:
- /**
- * Constructor
- * @param iterator The iterator that is implemented by the extension
- */
- IteratorImpl(Iterator *iterator) : _iterator(iterator)
- {
- // initialize impl object
- _impl.data = this;
- _impl.index = 0;
- _impl.funcs = functions();
- }
-
- /**
- * Destructor
- */
- virtual ~IteratorImpl() {}
-
- /**
- * Internal method that returns the implementation object
- * @return zend_object_iterator
- */
- zend_object_iterator *implementation()
- {
- return &_impl;
- }
-};
-
-/**
- * End namespace
- */
-}
diff --git a/src/member.h b/src/member.h
deleted file mode 100644
index 7aa01d8..0000000
--- a/src/member.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * Member.h
- *
- * Base class for properties of a class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013, 2014 Copernica BV
- */
-
-/**
- * Namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class Member
-{
-public:
- /**
- * Constructor
- * @param name Name of the member
- * @param flags Flag access to a class member (public, protected etc)
- */
- Member(const char *name, int flags) : _name(name), _flags(flags) {}
-
- /**
- * Destructor
- */
- virtual ~Member() {}
-
- /**
- * Initialize the member
- * @param zend_class_entry
- * @param tsrm_ls
- */
- void initialize(struct _zend_class_entry *entry TSRMLS_DC)
- {
- if (_flags == Const) constant(entry TSRMLS_CC);
- else declare(entry TSRMLS_CC);
- }
-
-protected:
- /**
- * Internal method to declare the property as constant
- * @param zend_class_entry
- * @param tsrm_ls
- */
- virtual void constant(struct _zend_class_entry *entry TSRMLS_DC) = 0;
-
- /**
- * Internal method to declare the property
- * @param zend_class_entry
- * @param tsrm_ls
- */
- virtual void declare(struct _zend_class_entry *entry TSRMLS_DC) = 0;
-
-protected:
- /**
- * The member name
- * @var std::string
- */
- std::string _name;
-
- /**
- * The member flags
- * @var int
- */
- int _flags;
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/members.cpp b/src/members.cpp
deleted file mode 100644
index 1965807..0000000
--- a/src/members.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- * Members.cpp
- *
- * Implementation of the members class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-///**
-// * Destructor
-// */
-//Members::~Members()
-//{
-// // check if there are methods
-// if (_methods) delete[] _methods;
-//}
-//
-///**
-// * Number of methods
-// * @return integer
-// */
-//int Members::methods()
-//{
-// // result variable
-// int result = 0;
-//
-// // loop through the functions
-// for (auto it = begin(); it != end(); it++)
-// {
-// // check if this is a method
-// if (it->isMethod()) result++;
-// }
-//
-// // done
-// return result;
-//}
-//
-///**
-// * Get access to the methods
-// * @return Methods
-// */
-//struct _zend_function_entry *Members::methods(const char *classname)
-//{
-// // already set?
-// if (_methods) return _methods;
-//
-// // the number of methods
-// int count = methods();
-//
-// // allocate memory for the functions
-// _methods = new zend_function_entry[count + 1];
-//
-// // keep iterator counter
-// int i = 0;
-//
-// // loop through the functions
-// for (auto it = begin(); it != end(); it++)
-// {
-// // skip if this is not a method
-// if (!it->isMethod()) continue;
-//
-// // retrieve entry
-// zend_function_entry *entry = &_methods[i++];
-//
-// // let the function fill the entry
-// it->initialize(classname, entry);
-// }
-//
-// // last entry should be set to all zeros
-// zend_function_entry *last = &_methods[i];
-//
-// // all should be set to zero
-// memset(last, 0, sizeof(zend_function_entry));
-//
-// // done
-// return _methods;
-//}
-//
-/**
- * End of namespace
- */
-}
-
diff --git a/src/method.h b/src/method.h
deleted file mode 100644
index dd18a9a..0000000
--- a/src/method.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- * Method.h
- *
- * Internal class that represents a native class method, that can be called
- * from PHP scripts.
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class Method : public Callable
-{
-public:
- /**
- * Constructor
- *
- * @param name Method name
- * @param callback Native callback
- * @param flags Access flags
- * @param args Argument description
- */
- Method(const char *name, const method_callback_0 &callback, int flags, const Arguments &args) : Callable(name, args), _type(0), _flags(flags) { _callback.m0 = callback; }
- Method(const char *name, const method_callback_1 &callback, int flags, const Arguments &args) : Callable(name, args), _type(1), _flags(flags) { _callback.m1 = callback; }
- Method(const char *name, const method_callback_2 &callback, int flags, const Arguments &args) : Callable(name, args), _type(2), _flags(flags) { _callback.m2 = callback; }
- Method(const char *name, const method_callback_3 &callback, int flags, const Arguments &args) : Callable(name, args), _type(3), _flags(flags) { _callback.m3 = callback; }
- Method(const char *name, const method_callback_4 &callback, int flags, const Arguments &args) : Callable(name, args), _type(4), _flags(flags) { _callback.m4 = callback; }
- Method(const char *name, const method_callback_5 &callback, int flags, const Arguments &args) : Callable(name, args), _type(5), _flags(flags) { _callback.m5 = callback; }
- Method(const char *name, const method_callback_6 &callback, int flags, const Arguments &args) : Callable(name, args), _type(6), _flags(flags) { _callback.m6 = callback; }
- Method(const char *name, const method_callback_7 &callback, int flags, const Arguments &args) : Callable(name, args), _type(7), _flags(flags) { _callback.m7 = callback; }
- Method(const char *name, const native_callback_0 &callback, int flags, const Arguments &args) : Callable(name, args), _type(8), _flags(flags) { _callback.m8 = callback; }
- Method(const char *name, const native_callback_1 &callback, int flags, const Arguments &args) : Callable(name, args), _type(9), _flags(flags) { _callback.m9 = callback; }
- Method(const char *name, const native_callback_2 &callback, int flags, const Arguments &args) : Callable(name, args), _type(10), _flags(flags) { _callback.m10 = callback; }
- Method(const char *name, const native_callback_3 &callback, int flags, const Arguments &args) : Callable(name, args), _type(11), _flags(flags) { _callback.m11 = callback; }
- Method(const char *name, int flags, const Arguments &args) : Callable(name, args), _type(9999), _flags(flags) { _callback.m0 = nullptr; }
-
- /**
- * Copy and move constructors
- * @param that
- */
- Method(const Method &that) : Callable(that), _type(that._type), _flags(that._flags), _callback(that._callback) {}
- Method(Method &&that) : Callable(std::move(that)), _type(that._type), _flags(that._flags), _callback(that._callback) {}
-
- /**
- * Destructor
- * @param type
- * @param callback
- */
- virtual ~Method() {}
-
- /**
- * Internal method to fill a function entry
- * @param zend_function_entry
- * @param classname
- */
- void initialize(struct _zend_function_entry *entry, const std::string &classname)
- {
- // fix the flags, if neither public, private and protected is set, we use public,
- // (this solves php warnings if only "final" or only "abstract" is set
- if ((_flags & (Public|Private|Protected)) == 0) _flags |= Public;
-
- // call base
- Callable::initialize(entry, classname.c_str(), _flags);
- }
-
- /**
- * Invoke the method
- * @param parameters
- * @return Value
- */
- virtual Value invoke(Parameters &parameters) override
- {
- // the object to call a method on
- Base *base = parameters.object();
-
- // find out which method to call, and call it
- switch (_type) {
- case 0: (base->*_callback.m0)(); return Value();
- case 1: (base->*_callback.m1)(parameters); return Value();
- case 2: return (base->*_callback.m2)();
- case 3: return (base->*_callback.m3)(parameters);
- case 4: (base->*_callback.m4)(); return Value();
- case 5: (base->*_callback.m5)(parameters); return Value();
- case 6: return (base->*_callback.m6)();
- case 7: return (base->*_callback.m7)(parameters);
- case 8: _callback.m8(); return Value();
- case 9: _callback.m9(parameters); return Value();
- case 10: return _callback.m10();
- case 11: return _callback.m11(parameters);
- default: return Value();
- }
- }
-
-
-private:
- /**
- * Callback type
- * @var int
- */
- int _type;
-
- /**
- * Access flags (protected, public, abstract, final, private, etc)
- * @var int
- */
- int _flags;
-
- /**
- * The actual callback
- * @var void*
- */
- union {
- method_callback_0 m0;
- method_callback_1 m1;
- method_callback_2 m2;
- method_callback_3 m3;
- method_callback_4 m4;
- method_callback_5 m5;
- method_callback_6 m6;
- method_callback_7 m7;
- native_callback_0 m8;
- native_callback_1 m9;
- native_callback_2 m10;
- native_callback_3 m11;
- } _callback;
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/modifiers.cpp b/src/modifiers.cpp
deleted file mode 100644
index 3720730..0000000
--- a/src/modifiers.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Modifiers.cpp
- *
- * In this file an enumeration type is with the possible
- * member modifiers
- *
- * @author Martijn Otto <martijn.otto@copernica.com>
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- *
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * The modifiers are constants
- */
-const int Static = 0x01;
-const int Abstract = 0x02;
-const int Final = 0x04;
-const int Public = 0x100;
-const int Protected = 0x200;
-const int Private = 0x400;
-const int Const = 0;
-
-/**
- * Modifiers that are supported for methods and properties
- */
-const int MethodModifiers = Final | Public | Protected | Private;
-const int PropertyModifiers = Final | Public | Protected | Private | Const | Static;
-
-/**
- * End namespace
- */
-}
diff --git a/src/namespace.cpp b/src/namespace.cpp
deleted file mode 100644
index bea31a1..0000000
--- a/src/namespace.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * Namespace.cpp
- *
- * Implementation of the namespace class
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Open namespace
- */
-namespace Php {
-
-/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- * @return Namespace Same object to allow chaining
- */
-Namespace &Namespace::add(const char *name, const native_callback_0 &function, const Arguments &arguments)
-{
- // add a function
- _functions.push_back(std::make_shared<Function>(name, function, arguments));
-
- // allow chaining
- return *this;
-}
-
-/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- * @return Namespace Same object to allow chaining
- */
-Namespace &Namespace::add(const char *name, const native_callback_1 &function, const Arguments &arguments)
-{
- // add a function
- _functions.push_back(std::make_shared<Function>(name, function, arguments));
-
- // allow chaining
- return *this;
-}
-
-/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- * @return Namespace Same object to allow chaining
- */
-Namespace &Namespace::add(const char *name, const native_callback_2 &function, const Arguments &arguments)
-{
- // add a function
- _functions.push_back(std::make_shared<Function>(name, function, arguments));
-
- // allow chaining
- return *this;
-}
-
-/**
- * Add a native function directly to the extension
- * @param name Name of the function
- * @param function The function to add
- * @param arguments Optional argument specification
- * @return Namespace Same object to allow chaining
- */
-Namespace &Namespace::add(const char *name, const native_callback_3 &function, const Arguments &arguments)
-{
- // add a function
- _functions.push_back(std::make_shared<Function>(name, function, arguments));
-
- // allow chaining
- return *this;
-}
-
-/**
- * Apply a callback to each registered function
- *
- * The callback will be called with the name of the namespace, and
- * a reference to the registered function.
- *
- * @param callback
- */
-void Namespace::apply(const std::function<void(const std::string &ns, Function &func)> &callback)
-{
- // loop through the functions, and apply the callback
- for (auto &function : _functions) callback(_name, *function);
-
- // loop through the other namespaces
- for (auto &ns : _namespaces) ns->apply([this, callback](const std::string &ns, Function &func) {
-
- // if this is the root namespace, we don't have to change the prefix
- if (_name.size() == 0) return callback(ns, func);
-
- // construct a new prefix
- // @todo this could be slightly inefficient
- return callback(_name + "\\" + ns, func);
- });
-}
-
-/**
- * Apply a callback to each registered class
- *
- * The callback will be called with the name of the namespace, and
- * a reference to the registered class.
- *
- * @param callback
- */
-void Namespace::apply(const std::function<void(const std::string &ns, ClassBase &clss)> &callback)
-{
- // loop through the classes, and apply the callback
- for (auto &c : _classes) callback(_name, *c);
-
- // loop through the other namespaces
- for (auto &ns : _namespaces) ns->apply([this, callback](const std::string &ns, ClassBase &clss) {
-
- // if this is the root namespace, we don't have to change the prefix
- if (_name.size() == 0) return callback(ns, clss);
-
- // construct a new prefix
- // @todo this could be slightly inefficient
- return callback(_name + "\\" + ns, clss);
- });
-}
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/notimplemented.h b/src/notimplemented.h
deleted file mode 100644
index ee99254..0000000
--- a/src/notimplemented.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * NotImplemented.h
- *
- * Exception that is thrown and catched by the library internally to detect
- * if a magic method was implemented or not.
- *
- * Classes have magic methods (like __unset, __isset, etcetera). These methods
- * can be implemented by the extension writer, but they do not have to be.
- *
- * The default implementation of the methods _could_ be to pass on the method
- * to the original Zend engine, but the problem is that the magic methods from
- * the PHP-CPP library do not have the same signature as the functions in the
- * Zend engine. Passing them on directly is thus not possible.
- *
- * For that reason, the default implementation throw an exception that is
- * immediately caught by the PHP-CPP library, so that it knows that the user
- * has not overridden the methods, and the default Zend engine magic method
- * can be called instead
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class NotImplemented : public std::exception
-{
-public:
- /**
- * Constructor
- */
- NotImplemented() : std::exception() {}
-
- /**
- * Destructor
- */
- virtual ~NotImplemented() throw() {}
-
-};
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/nullmember.h b/src/nullmember.h
deleted file mode 100644
index e035897..0000000
--- a/src/nullmember.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * NullMember.h
- *
- * Implementation for a property that is initially set to NULL
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class NullMember : public Member
-{
-public:
- /**
- * Constructor
- * @param name
- * @param flags
- */
- NullMember(const char *name, int flags) : Member(name, flags) {}
-
- /**
- * Destructor
- */
- virtual ~NullMember() {}
-
- /**
- * Internal method to declare the property as constant
- * @param zend_class_entry
- * @param tsrm_ls
- */
- virtual void constant(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- zend_declare_class_constant_null(entry, _name.c_str(), _name.size() TSRMLS_CC);
- }
-
- /**
- * Virtual method to declare the property
- * @param entry Class entry
- * @param tsrm_ls
- */
- virtual void declare(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- // char* cast is necessary for php 5.3
- zend_declare_property_null(entry, (char *)_name.c_str(), _name.size(), _flags TSRMLS_CC);
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/numericmember.h b/src/numericmember.h
deleted file mode 100644
index 0a040d3..0000000
--- a/src/numericmember.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * NumericMember.h
- *
- * Implementation for a property that is initially set to a numeric value
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013, 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class NumericMember : public Member
-{
-private:
- /**
- * The value
- * @var long
- */
- long _value;
-
-public:
- /**
- * Constructor
- * @param name
- * @param value
- * @param flags
- */
- NumericMember(const char *name, long value, int flags) : Member(name, flags), _value(value) {}
-
- /**
- * Destructor
- */
- virtual ~NumericMember() {}
-
- /**
- * Declare class constant
- * @param entry Class entry
- * @param tsrm_ls
- */
- virtual void constant(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- zend_declare_class_constant_long(entry, _name.c_str(), _name.size(), _value TSRMLS_CC);
- }
-
- /**
- * Virtual method to declare the property
- * @param entry Class entry
- * @param tsrm_ls
- */
- virtual void declare(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- // char* cast is necessary for php 5.3
- zend_declare_property_long(entry, (char *)_name.c_str(), _name.size(), _value, _flags TSRMLS_CC);
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/object.cpp b/src/object.cpp
deleted file mode 100644
index d7fc158..0000000
--- a/src/object.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * Object.cpp
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Constructor to create a new instance of a builtin class
- *
- * @param name Name of the class to instantiate
- * @param base Implementation of the class
- */
-Object::Object(const char *name, Base *base)
-{
- // does the object already have a handle?
- if (base->implementation())
- {
- // the object is already instantiated, we can assign it the this object
- operator=(Value(base));
- }
- else
- {
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // this is a brand new object that should be allocated, the C++ instance
- // is already there (created by the extension) but it is not yet stored
- // in PHP, find out the classname first
- auto *entry = zend_fetch_class(name, strlen(name), 0 TSRMLS_CC);
- if (!entry) throw Php::Exception(std::string("Unknown class name ") + name);
-
- // construct an implementation (this will also set the implementation
- // member in the base object)
- new ObjectImpl(entry, base TSRMLS_CC);
-
- // now we can store it
- operator=(Value(base));
- }
-}
-
-/**
- * Internal method to instantiate an object
- * @param name
- */
-void Object::instantiate(const char *name)
-{
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // convert the name into a class_entry
- auto *entry = zend_fetch_class(name, strlen(name), 0 TSRMLS_CC);
- if (!entry) throw Php::Exception(std::string("Unknown class name ") + name);
-
- // initiate the zval (which was already allocated in the base constructor)
- object_init_ex(_val, entry);
-
- // @todo should we call methods like allocating hashtables, copying and
- // initializing properties, et cetera????? In all example you always
- // see such complicated and next-to-impossible-to-understand
- // sequences of functions being called, but this object_init_ex
- // also seems to work...
-
- // @todo is this a memory leak? the base class first initializes a stdClass,
- // and then we overwrite it with a specific class
-
-}
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/objectimpl.h b/src/objectimpl.h
deleted file mode 100644
index 41bed53..0000000
--- a/src/objectimpl.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/**
- * ObjectImpl.h
- *
- * Implementation class for Base objects that allow the objects to be stored
- * in the Zend engine
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class ObjectImpl
-{
-private:
- /**
- * Structure with a first element which is a mixed object, so that
- * it can be casted to a zend_object
- * @var MixedObject
- */
- struct MixedObject
- {
- /**
- * The actual object is the first member, so that casting
- * the MixedObject to a zend_object will also result in a valid pointer
- * @var zend_object
- */
- zend_object php;
-
- /**
- * Pointer to ourselves
- * @var ObjectImpl
- */
- ObjectImpl *self;
-
-
- } _mixed;
-
- /**
- * Pointer to the C++ implementation
- * @var Base
- */
- Base *_object;
-
- /**
- * The object handle in the Zend engine
- * @var int
- */
- int _handle;
-
-public:
- /**
- * Constructor
- *
- * This will create a new object in the Zend engine.
- *
- * @param entry Zend class entry
- * @param base C++ object that already exists
- * @param tsrm_ls Optional threading data
- */
- ObjectImpl(zend_class_entry *entry, Base *base TSRMLS_DC)
- {
- // copy properties to the mixed object
- _mixed.php.ce = entry;
- _mixed.self = this;
-
- // store the c++ object
- _object = base;
-
- // initialize the object
- zend_object_std_init(&_mixed.php, entry TSRMLS_CC);
-
-#if PHP_VERSION_ID < 50399
-
- // tmp variable
- zval *tmp;
-
- // initialize the properties, php 5.3 way
- zend_hash_copy(_mixed.php.properties, &entry->default_properties, (copy_ctor_func_t) zval_property_ctor, &tmp, sizeof(zval*));
-
-#else
-
- // version higher than 5.3 have an easier way to initialize
- object_properties_init(&_mixed.php, entry);
-
-#endif
-
-#ifdef ZTS
-
- // when in thread safety mode, the destruct method and free method have
- // an extra parameter holding thread information
- using DestructType = void(zend_object*,unsigned int,void***);
- using FreeType = void(zend_object*,void***);
-
-#else
-
- // not in thread mode: no special parameter for the tsrm_ls variable
- using DestructType = void(zend_object*,unsigned int);
- using FreeType = void(zend_object*);
-
-#endif
-
- // store the two destruct methods in temporary vars
- DestructType *destructMethod = &ClassImpl::destructObject;
- FreeType *freeMethod = &ClassImpl::freeObject;
-
- // the destructor and clone handlers are set to NULL. I dont know why, but they do not
- // seem to be necessary...
- _handle = zend_objects_store_put(&_mixed, (zend_objects_store_dtor_t)destructMethod, (zend_objects_free_object_storage_t)freeMethod, NULL TSRMLS_CC);
-
- // the object may remember that we are its implementation object
- base->_impl = this;
- }
-
- /**
- * Destructor
- */
- virtual ~ObjectImpl()
- {
- // deallocate the cpp object
- delete _object;
- }
-
- /**
- * Destruct the object
- * @param tsrm_ls
- */
- void destruct(TSRMLS_D)
- {
- // pass on to the default destructor
- zend_objects_free_object_storage(&_mixed.php TSRMLS_CC);
-
- // destruct the object
- delete this;
- }
-
- /**
- * Find the object based on a zval
- * @param val Zval object
- * @param tsrm_ls Optional pointer to thread info
- * @return ObjectImpl
- */
- static ObjectImpl *find(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);
-
- // done
- return object->self;
- }
-
- /**
- * Find the object based on a zend_object
- * @param object Zend object pointer
- * @return ObjectImpl
- */
- static ObjectImpl *find(const zend_object *object)
- {
- // retrieve the old object, which we are going to copy
- const MixedObject *mixed = (MixedObject *)object;
-
- // done
- return mixed->self;
- }
-
- /**
- * Retrieve the base class of the original C++ object
- * @return Base
- */
- Base *object()
- {
- return _object;
- }
-
- /**
- * Pointer to the PHP object
- * @return zend_object
- */
- zend_object *php()
- {
- return &_mixed.php;
- }
-
- /**
- * Retrieve the handle object
- * @return int
- */
- int handle() const
- {
- return _handle;
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/origexception.h b/src/origexception.h
deleted file mode 100644
index 775e412..0000000
--- a/src/origexception.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/**
- * OrigException.h
- *
- * Class that wraps around an exception that was thrown by PHP code,
- * and that could - but not necessarily has to - be caught by C++
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class OrigException : public Value, public Exception
-{
-private:
- /**
- * Is this a an exception that was caught by extension C++ code.
- *
- * When the object is initially created, we assume that it will be caught
- * by C++ code. If it later turns out that the PHP-CPP can catch this
- * exception after the extension C++ code ran, the variable is set back
- * to false.
- *
- * @var bool
- */
- bool _handled = true;
-
-#ifdef ZTS
- /**
- * When we run in multi-thread mode, we store the thread handle
- * @var void***
- */
- TSRMLS_D;
-#endif
-
-public:
- /**
- * Constructor
- * @param val
- */
- OrigException(zval *val TSRMLS_DC) :
- Value(val), Exception("OrigException")
- {
-#ifdef ZTS
- // copy tsrm_ls
- this->TSRMLS_C = TSRMLS_C;
-#endif
- }
-
- /**
- * Copy constructor
- * @param exception
- */
- OrigException(const OrigException &exception) :
- Value(exception), Exception("OrigException"), _handled(exception._handled)
- {
-#ifdef ZTS
- // copy tsrm_ls
- TSRMLS_C = exception.TSRMLS_C;
-#endif
- }
-
- /**
- * Move constructor
- * @param exception
- */
- OrigException(OrigException &&exception) :
- Value(std::move(exception)), Exception("OrigException"), _handled(exception._handled)
- {
- // set other exception to handled so that it wont do anything on destruction
- exception._handled = true;
-
-#ifdef ZTS
- // copy tsrm_ls
- TSRMLS_C = exception.TSRMLS_C;
-#endif
- }
-
- /**
- * Destructor
- */
- virtual ~OrigException() throw()
- {
- // if the exception was not handled by C++ code, we're not going to do anything
- // and the exception stays active
- if (!_handled) return;
-
- // the exception was handled, so we should clean it up
- zend_clear_exception(TSRMLS_C);
- }
-
- /**
- * This is _not_ a native exception, it was thrown by a PHP script
- * @return bool
- */
- virtual bool native() const override
- {
- return false;
- }
-
- /**
- * Reactivate the exception
- */
- void reactivate()
- {
- // it was not handled by extension C++ code
- _handled = false;
- }
-};
-
-/**
- * Global function to process an exception
- * @param exception
- * @param tsrm_ls
- */
-inline void process(Exception &exception TSRMLS_DC)
-{
- // is this a native exception?
- if (exception.native())
- {
- // the exception is native, call the zend throw method
- zend_throw_exception(zend_exception_get_default(TSRMLS_C), (char *)exception.what(), 0 TSRMLS_CC);
- }
- else
- {
- // this is not a native exception, so it was originally thrown by a
- // php script, and then not caught by the c++ of the extensiont, we are
- // going to tell to the exception that it is still active
- OrigException &orig = static_cast<OrigException&>(exception);
-
- // reactive the exception
- orig.reactivate();
- }
-}
-
-/**
- * End of namespace
- */
-}
diff --git a/src/parametersimpl.h b/src/parametersimpl.h
deleted file mode 100644
index fd14238..0000000
--- a/src/parametersimpl.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/**
- * ParametersImpl.h
- *
- * Extended parameters class that can be instantiated
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class ParametersImpl : public Parameters
-{
-public:
- /**
- * Constructor
- * @param this_ptr Pointer to the object
- * @param argc Number of arguments
- * @param tsrm_ls
- */
- ParametersImpl(zval *this_ptr, int argc TSRMLS_DC) : Parameters(this_ptr ? ObjectImpl::find(this_ptr TSRMLS_CC)->object() : nullptr)
- {
- // reserve plenty of space
- reserve(argc);
-
- // loop through the arguments
- for (int i=0; i<argc; i++)
- {
- // get the argument
- zval **arg = (zval **) (zend_vm_stack_top(TSRMLS_C) - 1 - (argc-i));
-
- // append value
- push_back(Value(*arg));
- }
- }
-
- /**
- * Destructor
- */
- virtual ~ParametersImpl() {}
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/property.h b/src/property.h
deleted file mode 100644
index f0fd46f..0000000
--- a/src/property.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- * Property.h
- *
- * Internal class for properties that are defined with a getter and setter method
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class Property
-{
-private:
- /**
- * The getter
- * @var getter_callback
- */
- union {
- getter_callback_0 g0;
- getter_callback_1 g1;
- } _getter;
-
- /**
- * The setter
- * @var setter_callback
- */
- union {
- setter_callback_0 s0;
- setter_callback_1 s1;
- } _setter;
-
- /**
- * Type of getter
- * @var char
- */
- int _gtype = 0;
-
- /**
- * Type of setter
- * @var char
- */
- int _stype = 100;
-
-public:
- /**
- * Constructor
- * @param getter
- * @param setter
- */
- Property(const getter_callback_0 &getter) : _gtype(0)
- {
- _getter.g0 = getter;
- }
-
- /**
- * Constructor
- * @param getter
- * @param setter
- */
- Property(const getter_callback_1 &getter) : _gtype(1)
- {
- _getter.g1 = getter;
- }
-
-
- /**
- * Constructor
- * @param getter
- * @param setter
- */
- Property(const getter_callback_0 &getter, const setter_callback_0 &setter) : _gtype(0), _stype(0)
- {
- _getter.g0 = getter;
- _setter.s0 = setter;
- }
-
- /**
- * Constructor
- * @param getter
- * @param setter
- */
- Property(const getter_callback_1 &getter, const setter_callback_0 &setter) : _gtype(1), _stype(0)
- {
- _getter.g1 = getter;
- _setter.s0 = setter;
- }
-
- /**
- * Constructor
- * @param getter
- * @param setter
- */
- Property(const getter_callback_0 &getter, const setter_callback_1 &setter) : _gtype(0), _stype(1)
- {
- _getter.g0 = getter;
- _setter.s1 = setter;
- }
-
- /**
- * Constructor
- * @param getter
- * @param setter
- */
- Property(const getter_callback_1 &getter, const setter_callback_1 &setter) : _gtype(1), _stype(1)
- {
- _getter.g1 = getter;
- _setter.s1 = setter;
- }
-
- /**
- * Copy constructor
- * @param that
- */
- Property(const Property &that) :
- _getter(that._getter), _setter(that._setter), _gtype(that._gtype), _stype(that._stype) {}
-
- /**
- * Destructor
- */
- virtual ~Property() {}
-
- /**
- * Get the property
- * @param base Object to call it on
- * @return Value
- */
- Value get(Base *base)
- {
- if (_gtype == 0) return (base->*_getter.g0)();
- else return (base->*_getter.g1)();
- }
-
- /**
- * Set the property
- * @param base Object to call it on
- * @param value New value
- * @return bool
- */
- bool set(Base *base, const Value &value)
- {
- switch (_stype) {
- case 0: (base->*_setter.s0)(value); return true;
- case 1: (base->*_setter.s1)(value); return true;
- default: return false;
- }
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/streambuf.cpp b/src/streambuf.cpp
deleted file mode 100644
index e258b4e..0000000
--- a/src/streambuf.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * StreamBuf.cpp
- *
- * Implementation file for the StreamBuf class
- *
- * @see http://www.mr-edd.co.uk/blog/beginners_guide_streambuf
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Constructor
- * @param error
- */
-StreamBuf::StreamBuf(int error) : _error(error)
-{
- // we reserve one byte, so that when overflow is called, we still have one
- // byte extra in the buffer to put the overflowed byte int
- setp(_buffer, _buffer+1024-1);
-}
-
-
-/**
- * Method that is called when the internal buffer overflows
- * @param c
- * @return int
- */
-int StreamBuf::overflow(int c)
-{
- // for error buffers, overflow is simply discarded
- if (_error) return c;
-
- // end-of-file has not output, we call EOF directly, and by using the
- // comma operator we ensure that EOF is returned
- if (c == EOF) return sync(), EOF;
-
- // because we lied the underlying buffer about the size of the buffer
- // by one byte, there is no real overflow, and we can still add the byte
- // to the end of the buffer
- *pptr() = c;
-
- // increment buffer size
- pbump(1);
-
- // and now we're going to syn the buffer
- return sync() == -1 ? EOF : c;
-}
-
-/**
- * Called when the internal buffer should be synchronized
- * @return int
- */
-int StreamBuf::sync()
-{
- // current buffer size
- size_t size = pptr() - pbase();
-
- // is this the error stream or the regular output stream?
- if (_error)
- {
- // write to error (the zend_error() method is a varargs function,
- // which means that we have to include a printf() like format as first
- // parameter. We can not specify pbase() directly, because (1) it is
- // not null terminated and (2) it could contain % signs and allow all
- // sorts of buffer overflows.
- zend_error(_error, "%.*s", (int)size, pbase());
-
- }
- else
- {
- // write to zend
- zend_write(pbase(), size);
- }
-
- // reset the buffer
- pbump(-size);
-
- // done
- return 0;
-}
-
-/**
- * End namespace
- */
-}
- \ No newline at end of file
diff --git a/src/streambuf.h b/src/streambuf.h
deleted file mode 100644
index ed1506a..0000000
--- a/src/streambuf.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * StreamBuf.h
- *
- * PHP output stream buffer which is used by the Php::out object to
- * have an output stream just like the regular std::ostream buffers,
- * but that sends all output to PHP output
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class StreamBuf : public std::streambuf
-{
-public:
- /**
- * Constructor
- * @param error the error type, or 0 for regular output
- */
- StreamBuf(int error);
-
- /**
- * No copying or moving
- * @param that
- */
- StreamBuf(const StreamBuf &that) = delete;
- StreamBuf(StreamBuf &&that) = delete;
-
- /**
- * Destructor
- */
- virtual ~StreamBuf() {}
-
- /**
- * No copying or moving
- * @param that
- */
- StreamBuf &operator=(const StreamBuf &that) = delete;
- StreamBuf &operator=(StreamBuf &&that) = delete;
-
-protected:
- /**
- * Method that is called when the internal buffer overflows
- * @param c
- * @return int
- */
- virtual int overflow(int c = EOF) override;
-
- /**
- * Called when the internal buffer should be synchronized
- * @return int
- */
- virtual int sync() override;
-
-private:
- /**
- * The error type, or 0 for regular output
- * @var int
- */
- int _error;
-
- /**
- * The internal buffer
- * @var char[]
- */
- char _buffer[1024];
-};
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/streams.cpp b/src/streams.cpp
deleted file mode 100644
index ba6d916..0000000
--- a/src/streams.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Streams.cpp
- *
- * Implementation of the streams
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Some static buffers for writing data
- * @var StreamBuf
- */
-static StreamBuf bufOut (0);
-static StreamBuf bufError (E_ERROR);
-static StreamBuf bufWarning (E_WARNING);
-static StreamBuf bufNotice (E_NOTICE);
-static StreamBuf bufDeprecated (E_DEPRECATED);
-
-/**
- * Create the actual steams
- * @var std::ostream
- */
-std::ostream out (&bufOut);
-std::ostream error (&bufError);
-std::ostream warning (&bufWarning);
-std::ostream notice (&bufNotice);
-std::ostream deprecated (&bufDeprecated);
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/stringmember.h b/src/stringmember.h
deleted file mode 100644
index e58cd3d..0000000
--- a/src/stringmember.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- * StringMember.h
- *
- * Implementation for a property that is initially set to a strnig value
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class StringMember : public Member
-{
-private:
- /**
- * The value
- * @var string
- */
- std::string _value;
-
-public:
- /**
- * Constructor
- * @param name
- * @param value
- * @param size
- * @param flags
- */
- StringMember(const char *name, const char *value, size_t size, int flags) : Member(name, flags), _value(value, size) {}
-
- /**
- * Constructor
- * @param name
- * @param value
- * @param flags
- */
- StringMember(const char *name, const char *value, int flags) : StringMember(name, value, strlen(value), flags) {}
-
- /**
- * Constructor
- * @param name
- * @param value
- * @param flags
- */
- StringMember(const char *name, const std::string &value, int flags) : Member(name, flags), _value(value) {}
-
- /**
- * Destructor
- */
- virtual ~StringMember() {}
-
- /**
- * Virtual method to declare class constant
- * @param entry Class entry
- * @param tsrm_ls
- */
- virtual void constant(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- zend_declare_class_constant_stringl(entry, _name.c_str(), _name.size(), _value.c_str(), _value.size() TSRMLS_CC);
- }
-
- /**
- * Virtual method to declare the property
- * @param entry Class entry
- */
- virtual void declare(struct _zend_class_entry *entry TSRMLS_DC) override
- {
- // cast to char* is necessary for php 5.3
- zend_declare_property_stringl(entry, (char *)_name.c_str(), _name.size(), (char *)_value.c_str(), _value.size(), _flags TSRMLS_CC);
- }
-};
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/super.cpp b/src/super.cpp
deleted file mode 100644
index 506d4a5..0000000
--- a/src/super.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * Super.cpp
- *
- * @copyright 2014 Copernica BV
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * A number of super-globals are always accessible
- */
-Super POST (TRACK_VARS_POST, "_POST");
-Super GET (TRACK_VARS_GET, "_GET");
-Super COOKIE (TRACK_VARS_COOKIE, "_COOKIE");
-Super SERVER (TRACK_VARS_SERVER, "_SERVER");
-Super ENV (TRACK_VARS_ENV, "_ENV");
-Super FILES (TRACK_VARS_FILES, "_FILES");
-Super REQUEST (TRACK_VARS_REQUEST, "_REQUEST");
-
-/**
- * Array access operator
- * This can be used for accessing associative arrays
- * @param key
- * @return Value
- */
-Value Super::operator[](const std::string &key)
-{
- // we need the tsrm_ls pointer
- TSRMLS_FETCH();
-
- // call zend_is_auto_global to ensure that the just-in-time globals are loaded
- if (_name) { zend_is_auto_global(_name, strlen(_name) TSRMLS_CC); _name = nullptr; }
-
- // create a value object that wraps around the actual zval
- Value value(PG(http_globals)[_index]);
-
- // pass on the call
- return value[key];
-}
-
-/**
- * Array access operator
- * This can be used for accessing associative arrays
- * @param key
- * @return Value
- */
-Value Super::operator[](const char *key)
-{
- // we need the tsrm_ls pointer
- TSRMLS_FETCH();
-
- // call zend_is_auto_global to ensure that the just-in-time globals are loaded
- if (_name) { zend_is_auto_global(_name, strlen(_name) TSRMLS_CC); _name = nullptr; }
-
- // create a value object that wraps around the actual zval
- Value value(PG(http_globals)[_index]);
-
- // pass on the call
- return value[key];
-}
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/traverseiterator.h b/src/traverseiterator.h
deleted file mode 100644
index 16f1ce7..0000000
--- a/src/traverseiterator.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/**
- * TraverseIterator.h
- *
- * When an object from PHP userspace implements its own iterator methods,
- * and the Php::Value object is used to iterate over its properties, this
- * TraversableIterator class is used to iterate over the properties
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class TraverseIterator : public ValueIteratorImpl
-{
-public:
- /**
- * Constructor
- * @param object
- * @param begin
- * @param tsrm_ls
- */
- TraverseIterator(zval *object, bool begin TSRMLS_DC) : _object(object)
- {
- // leap out if this iterator starts at the end
- if (!begin) return;
-
- // we need the class entry
- auto *entry = zend_get_class_entry(object TSRMLS_CC);
-
- // create the iterator
- _iter = entry->get_iterator(entry, object, false TSRMLS_CC);
-
- // rewind the iterator
- _iter->funcs->rewind(_iter TSRMLS_CC);
-
- // read the first key/value pair
- read(TSRMLS_C);
- }
-
- /**
- * Copy constructor
- * @param that
- * @param tsrm_ls
- */
- TraverseIterator(const TraverseIterator &that TSRMLS_DC) : TraverseIterator(that._object, that._iter != nullptr TSRMLS_CC)
- {
- // @todo this is a broken implementation, the copy is at the start
- // position, while we'd like to be at the same position
- }
-
- /**
- * Destructor
- */
- virtual ~TraverseIterator()
- {
- // do nothing if iterator is already invalid
- if (!_iter) return;
-
- // we need the tsrm pointer
- TSRMLS_FETCH();
-
- // call the iterator destructor
- if (_iter) _iter->funcs->dtor(_iter TSRMLS_CC);
- }
-
- /**
- * Clone the object
- * @param tsrm_ls
- * @return ValueIteratorImpl*
- */
- virtual ValueIteratorImpl *clone() override
- {
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // construct iterator
- return new TraverseIterator(*this TSRMLS_CC);
- }
-
- /**
- * Increment position (pre-increment)
- * @param tsrm_ls
- * @return bool
- */
- virtual bool increment() override
- {
- // do we still have an iterator?
- if (!_iter) return false;
-
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // movw it forward
- _iter->funcs->move_forward(_iter TSRMLS_CC);
-
- // and read current data
- read(TSRMLS_C);
- }
-
- /**
- * Decrement position (pre-decrement)
- * @return bool
- */
- virtual bool decrement() override
- {
- // not possible with PHP iterators
- throw Exception("Impossible to iterate backwards");
- }
-
- /**
- * Compare with other iterator
- * @param that
- * @return bool
- */
- virtual bool equals(const ValueIteratorImpl *that) const override
- {
- // of course if the objects are identical
- if (this == that) return true;
-
- // cast to traverse-iterator
- TraverseIterator *other = (TraverseIterator *)that;
-
- // if both objects are in an invalid state we consider them to be identical
- if (!_iter && !other->_iter) return true;
-
- // although the iterators could be at the same pos, for simplicity
- // we consider them different here
- return false;
- }
-
- /**
- * Derefecence, this returns a std::pair with the current key and value
- * @return std::pair
- */
- virtual const std::pair<Value,Value> &current() const
- {
- return _data;
- }
-
-private:
- /**
- * The object that is iterated over
- * @var _val
- */
- zval *_object = nullptr;
-
- /**
- * The iterator from Zend
- * @var zend_object_iterator
- */
- struct _zend_object_iterator *_iter = nullptr;
-
- /**
- * Current data
- * @var pair
- */
- std::pair<Value,Value> _data;
-
-
- /**
- * Read current data
- * @param tsrm_ls
- * @return bool
- */
- bool read(TSRMLS_D)
- {
- // not possible when no iterator exists
- if (!_iter) return false;
-
- // is the iterator at a valid position?
- if (_iter->funcs->valid(_iter TSRMLS_CC) == FAILURE) return invalidate(TSRMLS_C);
-
-#if PHP_VERSION_ID >= 50500
-
- // create a value object
- Value val;
-
- // call the function to get the key
- _iter->funcs->get_current_key(_iter, val._val TSRMLS_CC);
-
- // store the key
- _data.first = val;
-
-#else
-
- // variable we need for fetching the key, and that will be assigned by
- // the PHP engine (this is php 5.3 code)
- char *str_key; unsigned int str_key_len; unsigned long int_key;
-
- // php 5.4 or php 5.3 code, fetch the current key
- int type = _iter->funcs->get_current_key(_iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
-
- // what sort of key do we have?
- if (type == HASH_KEY_IS_LONG)
- {
- // we have an int key
- _data.first = (int64_t)int_key;
- }
- else
- {
- // we have a string key that is already allocated
- _data.first = str_key;
-
- // deallocate the data
- efree(str_key);
- }
-
-#endif
-
- // now we're going to fetch the value, for this we need a strange zval
- // it is strange that this is a pointer-to-pointer, but that is how
- // the Zend engine implements this. It is going to be filled with
- // a pointer to a memory address that is guaranteed to hold a valid
- // zval.
- zval **zval;
-
- // get the current value
- _iter->funcs->get_current_data(_iter, &zval TSRMLS_CC);
-
- // wrap the zval in a value object
- _data.second = Value(*zval);
-
- // done
- return true;
- }
-
- /**
- * Invalidate the object
- * @param tsrm_ls
- * @return bool
- */
- bool invalidate(TSRMLS_D)
- {
- // skip if already invalid
- if (!_iter) return false;
-
- // reset the iterator
- _iter->funcs->dtor(_iter TSRMLS_CC);
-
- // set back to null
- _iter = nullptr;
-
- // done
- return false;
- }
-};
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/value.cpp b/src/value.cpp
deleted file mode 100644
index 2ca1585..0000000
--- a/src/value.cpp
+++ /dev/null
@@ -1,1911 +0,0 @@
-/**
- * Value.cpp
- *
- * Implementation for the Value class, which wraps a PHP userspace
- * value (a 'zval' in Zend's terminology) into a C++ object
- *
- * Reminder for the implementer:
- *
- * A 'zval' is an object that represents a _value_ in the PHP user space,
- * and thus not a variable. A 'value' or 'zval' can be used by many
- * different variables at the same time. The 'refcount' property of the
- * zval holds the number of variables ($a, $b, $c, et cetera) that are
- * all linked to the same value. With this system, PHP can implement copy
- * on write behavior.
- *
- * Next to the refcount, the zval also holds a is_ref property, which is
- * set to true if all variables linked to the value are references of each
- * other. Thus is $a, $b and $c all point to the same variable, and is_ref
- * is set to true, changing the value means that the $a, $b and $c value
- * are all updated. If is_res was false, a change to $a would not mean a
- * change to $b, and the zval should have been copied first.
- *
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2013, 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Constructor (value = NULL)
- */
-Value::Value()
-{
- // create a null zval
- MAKE_STD_ZVAL(_val);
- ZVAL_NULL(_val);
-}
-
-/**
- * Constructor for null ptr
-*/
-Value::Value(std::nullptr_t value)
-{
- // create a null zval
- MAKE_STD_ZVAL(_val);
- ZVAL_NULL(_val);
-}
-
-/**
- * Constructor based on integer value
- * @param value
- */
-Value::Value(int16_t value)
-{
- // create an integer zval
- MAKE_STD_ZVAL(_val);
- ZVAL_LONG(_val, value);
-}
-
-/**
- * Constructor based on integer value
- * @param value
- */
-Value::Value(int32_t value)
-{
- // create an integer zval
- MAKE_STD_ZVAL(_val);
- ZVAL_LONG(_val, value);
-}
-
-/**
- * Constructor based on int64_t value
- * @param value
- */
-Value::Value(int64_t value)
-{
- // create an integer zval
- MAKE_STD_ZVAL(_val);
- ZVAL_LONG(_val, value);
-}
-
-/**
- * Constructor based on boolean value
- * @param value
- */
-Value::Value(bool value)
-{
- // create a boolean zval
- MAKE_STD_ZVAL(_val);
- ZVAL_BOOL(_val, value);
-}
-
-/**
- * Constructor based on single character
- * @param value
- */
-Value::Value(char value)
-{
- // create a string zval
- MAKE_STD_ZVAL(_val);
- ZVAL_STRINGL(_val, &value, 1, 1);
-}
-
-/**
- * Constructor based on string value
- * @param value
- */
-Value::Value(const std::string &value)
-{
- // create a string zval
- MAKE_STD_ZVAL(_val);
- ZVAL_STRINGL(_val, value.c_str(), value.size(), 1);
-}
-
-/**
- * Constructor based on a byte array
- * @param value
- * @param size
- */
-Value::Value(const char *value, int size)
-{
- // create a string zval
- MAKE_STD_ZVAL(_val);
- ZVAL_STRINGL(_val, value, size < 0 ? strlen(value) : size, 1);
-}
-
-/**
- * Constructor based on decimal value
- * @param value
- */
-Value::Value(double value)
-{
- // create a double zval
- MAKE_STD_ZVAL(_val);
- ZVAL_DOUBLE(_val, value);
-}
-
-/**
- * Wrap object around zval
- * @param zval Value to wrap
- * @param ref Force this to be a reference
- */
-Value::Value(struct _zval_struct *val, bool ref)
-{
- // just copy the zval into this object
- _val = val;
-
- // if the variable is not already a reference, and it has more than one
- // variable pointing to it, we should seperate it so that any changes
- // we're going to make will not change the other variable
- if (ref && Z_REFCOUNT_P(_val) > 1)
- {
- // separate the zval
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
- }
-
- // we see ourselves as reference too
- Z_ADDREF_P(_val);
-
- // we're ready if we do not have to force it as a reference
- if (!ref || Z_ISREF_P(_val)) return;
-
- // make this a reference
- Z_SET_ISREF_P(_val);
-}
-
-/**
- * Wrap around an object
- * @param object
- */
-Value::Value(const Base *object)
-{
- // there are two options: the object was constructed from user space,
- // and is already linked to a handle, or it was constructed from C++
- // space, and no handle does yet exist, find the implementation object
- auto *impl = object->implementation();
-
- // do we have a handle?
- if (!impl) throw Php::Exception("Assigning an unassigned object to a variable");
-
- // make a regular zval, and set it to an object
- MAKE_STD_ZVAL(_val);
- Z_TYPE_P(_val) = IS_OBJECT;
- Z_OBJ_HANDLE_P(_val) = impl->handle();
-
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // we have to lookup the object in the object-table
- zend_object_store_bucket *obj_bucket = &EG(objects_store).object_buckets[impl->handle()];
-
- // this is copy-pasted from zend_objects.c - and it is necessary too!
- if (!obj_bucket->bucket.obj.handlers) obj_bucket->bucket.obj.handlers = &std_object_handlers;
-
- // store the handlers in the zval too (cast is necessary for php 5.3)
- Z_OBJ_HT_P(_val) = (zend_object_handlers*)obj_bucket->bucket.obj.handlers;
-
- // run the copy constructor
- zval_copy_ctor(_val);
-}
-
-/**
- * Copy constructor
- * @param value
- */
-Value::Value(const Value &that)
-{
- // is the other variable a reference?
- if (Z_ISREF_P(that._val))
- {
- // because this is supposed to be a COPY, we can not add ourselves
- // to the variable but have to allocate a new variable
- ALLOC_ZVAL(_val);
- INIT_PZVAL_COPY(_val, that._val);
-
- // we have to call the copy constructor to copy the entire other zval
- zval_copy_ctor(_val);
- }
- else
- {
- // simply use the same zval
- _val = that._val;
- }
-
- // that zval has one more reference
- Z_ADDREF_P(_val);
-
-
-// Below the old implementation - I thought really hard about it and I though
-// it was a correct and very smart implementation. However, it does not work
-// when you swap two variables. I changed it to the implementation above, but
-// maybe that implementation introduces other bugs??? Let's keep the old
-// implementation for a while in this file, but commented out
-//
-// // how many references does the other object have?
-// if (Z_REFCOUNT_P(that._val) > 1 && !Z_ISREF_P(that._val))
-// {
-// // there are already multiple variables linked to this value, and it
-// // is not a reference. this implies that we can not turn this variable
-// // into a reference, otherwise strange things could happen, we're going
-// // to create a new zval
-// ALLOC_ZVAL(_val);
-// INIT_PZVAL_COPY(_val, that._val);
-// zval_copy_ctor(_val);
-// }
-// else
-// {
-// // simply use the same zval
-// _val = that._val;
-// }
-//
-// // the other object only has one variable using it, or it is already
-// // a variable by reference, we can safely add one more reference to it
-// // and make it a variable by reference if it was not already a ref
-// Z_ADDREF_P(_val);
-//
-// // make reference
-// Z_SET_ISREF_P(_val);
-}
-
-/**
- * Move constructor
- * @param value
- */
-Value::Value(Value &&that) : _val(that._val)
-{
- // clear the other object
- that._val = nullptr;
-}
-
-/**
- * Destructor
- */
-Value::~Value()
-{
- // ignore if moved
- if (!_val) return;
-
- // if there were two references or less, we're going to remove a reference
- // and only one reference will remain, the object will then impossible be
- // a reference
- if (Z_REFCOUNT_P(_val) <= 2) Z_UNSET_ISREF_P(_val);
-
- // destruct the zval (this function will decrement the reference counter,
- // and only destruct if there are no other references left)
- zval_ptr_dtor(&_val);
-}
-
-/**
- * Detach the zval
- *
- * This will unlink the zval internal structure from the Value object,
- * so that the destructor will not reduce the number of references and/or
- * deallocate the zval structure. This is used for functions that have to
- * return a zval pointer, that would otherwise be deallocated the moment
- * the function returns.
- *
- * @return zval
- */
-zval *Value::detach()
-{
- // leap out if already detached
- if (!_val) return nullptr;
-
- // copy return value
- zval *result = _val;
-
- // decrement reference counter
- Z_DELREF_P(_val);
-
- // reset internal object
- _val = nullptr;
-
- // done
- return result;
-}
-
-/**
- * Attach a different zval
- *
- * This will first detach the current zval, and link the Value object to
- * a different zval.
- *
- * @param val
- */
-void Value::attach(struct _zval_struct *val)
-{
- // detach first
- if (_val) detach();
-
- // store the zval
- _val = val;
-
- // add one more reference
- Z_ADDREF_P(_val);
-}
-
-/**
- * Attach a different zval
- *
- * This will first detach the current zval, and link the Value object to
- * a new zval
- *
- * @param hashtable
- */
-void Value::attach(struct _hashtable *hashtable)
-{
- // detach first
- if (_val) detach();
-
- // construct a new zval
- MAKE_STD_ZVAL(_val);
-
- // store pointer to the hashtable, and mark the zval as an array
- Z_ARRVAL_P(_val) = hashtable;
- Z_TYPE_P(_val) = IS_ARRAY;
-
- // add a reference
- Z_ADDREF_P(_val);
-}
-
-/**
- * Retrieve the refcount
- * @return int
- */
-int Value::refcount()
-{
- return Z_REFCOUNT_P(_val);
-}
-
-/**
- * Move operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(Value &&value)
-{
- // skip self assignment
- if (this == &value) return *this;
-
- // is the object a reference?
- if (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
- Z_SET_ISREF_TO_P(_val, true);
- 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
- {
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // the last and only reference to the other object was
- // removed, we no longer need it
- FREE_ZVAL(value._val);
-
- // the other object is no longer valid
- value._val = nullptr;
- }
- }
- else
- {
- // destruct the zval (this function will decrement the reference counter,
- // and only destruct if there are no other references left)
- zval_ptr_dtor(&_val);
-
- // just copy the zval completely
- _val = value._val;
-
- // the other object is no longer valid
- value._val = nullptr;
- }
-
- // done
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(const Value &value)
-{
- // skip self assignment
- if (this == &value) return *this;
-
- // is the object a reference?
- if (Z_ISREF_P(_val))
- {
- // 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);
-
- // clean up the current zval (but keep the zval structure)
- zval_dtor(_val);
-
- // make the copy
- *_val = *value._val;
- zval_copy_ctor(_val);
-
- // restore refcount and reference setting
- Z_SET_ISREF_TO_P(_val, true);
- Z_SET_REFCOUNT_P(_val, refcount);
- }
- else
- {
- // destruct the zval (this function will decrement the reference counter,
- // and only destruct if there are no other references left)
- zval_ptr_dtor(&_val);
-
- // just copy the zval, and the refcounter
- _val = value._val;
-
- // and we have one more reference
- Z_ADDREF_P(_val);
- }
-
- // update the object
- return *this;
-}
-
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(std::nullptr_t value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // change to null value
- ZVAL_NULL(_val);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(int16_t value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_LONG(_val, value);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(int32_t value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_LONG(_val, value);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(int64_t value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_LONG(_val, value);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(bool value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_BOOL(_val, value);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(char value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_STRINGL(_val, &value, 1, 1);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(const std::string &value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_STRINGL(_val, value.c_str(), value.size(), 1);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(const char *value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_STRING(_val, value, 1);
-
- // update the object
- return *this;
-}
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value &Value::operator=(double value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // deallocate current zval (without cleaning the zval structure)
- zval_dtor(_val);
-
- // set new value
- ZVAL_DOUBLE(_val, value);
-
- // update the object
- return *this;
-}
-
-/**
- * Add a value to the object
- * @param value
- * @return Value
- */
-Value &Value::operator+=(const Value &value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(int16_t value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(int32_t value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(int64_t value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(bool value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(char value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(const std::string &value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(const char *value) { return Arithmetic<std::plus>(this).assign(value); }
-Value &Value::operator+=(double value) { return Arithmetic<std::plus>(this).assign(value); }
-
-/**
- * Subtract a value from the object
- * @param value
- * @return Value
- */
-Value &Value::operator-=(const Value &value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(int16_t value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(int32_t value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(int64_t value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(bool value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(char value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(const std::string &value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(const char *value) { return Arithmetic<std::minus>(this).assign(value); }
-Value &Value::operator-=(double value) { return Arithmetic<std::minus>(this).assign(value); }
-
-/**
- * Multiply the object with a certain value
- * @param value
- * @return Value
- */
-Value &Value::operator*=(const Value &value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(int16_t value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(int32_t value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(int64_t value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(bool value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(char value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(const std::string &value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(const char *value) { return Arithmetic<std::multiplies>(this).assign(value); }
-Value &Value::operator*=(double value) { return Arithmetic<std::multiplies>(this).assign(value); }
-
-/**
- * Divide the object with a certain value
- * @param value
- * @return Value
- */
-Value &Value::operator/=(const Value &value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(int16_t value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(int32_t value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(int64_t value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(bool value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(char value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(const std::string &value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(const char *value) { return Arithmetic<std::divides>(this).assign(value); }
-Value &Value::operator/=(double value) { return Arithmetic<std::divides>(this).assign(value); }
-
-/**
- * Divide the object with a certain value and get the rest
- * Note that this does not use the Arithmetic object, because no conversion between floats is necessary
- * @param value
- * @return Value
- */
-Value &Value::operator%=(const Value &value) { return operator=(numericValue() % value.numericValue()); }
-Value &Value::operator%=(int16_t value) { return operator=(numericValue() % value); }
-Value &Value::operator%=(int32_t value) { return operator=(numericValue() % value); }
-Value &Value::operator%=(int64_t value) { return operator=(numericValue() % value); }
-Value &Value::operator%=(bool value) { return operator=(numericValue() % value); }
-Value &Value::operator%=(char value) { return operator=(numericValue() % value); }
-Value &Value::operator%=(const std::string &value) { return operator=(numericValue() % atoi(value.c_str())); }
-Value &Value::operator%=(const char *value) { return operator=(numericValue() % atoi(value)); }
-Value &Value::operator%=(double value) { return operator=(numericValue() % (int)value); }
-
-/**
- * Assignment operator
- * @param value
- * @return Value
- */
-Value Value::operator+(const Value &value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(int16_t value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(int32_t value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(int64_t value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(bool value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(char value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(const std::string &value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(const char *value) { return Arithmetic<std::plus>(this).apply(value); }
-Value Value::operator+(double value) { return Arithmetic<std::plus>(this).apply(value); }
-
-/**
- * Subtraction operator
- * @param value
- * @return Value
- */
-Value Value::operator-(const Value &value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(int16_t value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(int32_t value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(int64_t value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(bool value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(char value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(const std::string &value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(const char *value) { return Arithmetic<std::minus>(this).apply(value); }
-Value Value::operator-(double value) { return Arithmetic<std::minus>(this).apply(value); }
-
-/**
- * Multiplication operator
- * @param value
- * @return Value
- */
-Value Value::operator*(const Value &value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(int16_t value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(int32_t value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(int64_t value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(bool value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(char value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(const std::string &value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(const char *value) { return Arithmetic<std::multiplies>(this).apply(value); }
-Value Value::operator*(double value) { return Arithmetic<std::multiplies>(this).apply(value); }
-
-/**
- * Division operator
- * @param value
- * @return Value
- */
-Value Value::operator/(const Value &value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(int16_t value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(int32_t value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(int64_t value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(bool value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(char value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(const std::string &value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(const char *value) { return Arithmetic<std::divides>(this).apply(value); }
-Value Value::operator/(double value) { return Arithmetic<std::divides>(this).apply(value); }
-
-/**
- * Modulus operator
- * @param value
- * @return Value
- */
-Value Value::operator%(const Value &value) { return Value(numericValue() % value.numericValue()); }
-Value Value::operator%(int16_t value) { return Value(numericValue() % value); }
-Value Value::operator%(int32_t value) { return Value(numericValue() % value); }
-Value Value::operator%(int64_t value) { return Value(numericValue() % value); }
-Value Value::operator%(bool value) { return Value(numericValue() % value); }
-Value Value::operator%(char value) { return Value(numericValue() % value); }
-Value Value::operator%(const std::string &value) { return Value(numericValue() % atoi(value.c_str())); }
-Value Value::operator%(const char *value) { return Value(numericValue() % atoi(value)); }
-Value Value::operator%(double value) { return Value(numericValue() % (int)value); }
-
-/**
- * Call the function in PHP
- * We have ten variants of this function, depending on the number of parameters
- * This call operator is only useful when the variable represents a callable
- * @param p0-p10 Parameters of the function to be called.
- * @return Value
- */
-Value Value::operator()() const
-{
- // call with zero parameters
- return exec(0, NULL);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @return Value
- */
-Value Value::operator()(Value p0) const
-{
- // array of parameters
- zval **params[1] = { &p0._val };
-
- // call the function
- return exec(1, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1) const
-{
- // array of parameters
- zval **params[2] = { &p0._val, &p1._val };
-
- // call the function
- return exec(2, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2) const
-{
- // array of parameters
- zval **params[3] = { &p0._val, &p1._val, &p2._val };
-
- // call the function
- return exec(3, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2, Value p3) const
-{
- // array of parameters
- zval **params[4] = { &p0._val, &p1._val, &p2._val, &p3._val };
-
- // call the function
- return exec(4, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2, Value p3, Value p4) const
-{
- // array of parameters
- zval **params[5] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val };
-
- // call the function
- return exec(5, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2, Value p3, Value p4, Value p5) const
-{
- // array of parameters
- zval **params[6] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val };
-
- // call the function
- return exec(6, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6) const
-{
- // array of parameters
- zval **params[7] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val };
-
- // call the function
- return exec(7, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eighth parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7) const
-{
- // array of parameters
- zval **params[8] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val };
-
- // call the function
- return exec(8, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eighth parameter
- * @param p8 The ninth parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8) const
-{
- // array of parameters
- zval **params[9] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val, &p8._val };
-
- // call the function
- return exec(9, params);
-}
-
-/**
- * Call the function - if the variable holds a callable thing
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eighth parameter
- * @param p8 The ninth parameter
- * @param p9 The tenth parameter
- * @return Value
- */
-Value Value::operator()(Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8, Value p9) const
-{
- // array of parameters
- zval **params[10] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val, &p8._val, &p9._val };
-
- // call the function
- return exec(10, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @return Value
- */
-Value Value::call(const char *name)
-{
- // call with zero parameters
- return exec(name, 0, NULL);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0)
-{
- // array of parameters
- zval **params[] = { &p0._val };
-
- // call with zero parameters
- return exec(name, 1, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val };
-
- // call with zero parameters
- return exec(name, 2, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val };
-
- // call with zero parameters
- return exec(name, 3, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2, Value p3)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val, &p3._val };
-
- // call with zero parameters
- return exec(name, 4, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val };
-
- // call with zero parameters
- return exec(name, 5, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val };
-
- // call with zero parameters
- return exec(name, 6, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val };
-
- // call with zero parameters
- return exec(name, 7, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eighth parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val };
-
- // call with zero parameters
- return exec(name, 8, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eighth parameter
- * @param p8 The ninth parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val, &p8._val };
-
- // call with zero parameters
- return exec(name, 9, params);
-}
-
-/**
- * Call the method - if the variable holds an object with the given method
- * @param name name of the method to call
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eighth parameter
- * @param p8 The ninth parameter
- * @param p9 The tenth parameter
- * @return Value
- */
-Value Value::call(const char *name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8, Value p9)
-{
- // array of parameters
- zval **params[] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val, &p8._val, &p9._val };
-
- // call with zero parameters
- return exec(name, 10, params);
-}
-
-/**
- * Helper function that runs the actual call
- * @param object The object to call it on
- * @param method The function or method to call
- * @param args Number of arguments
- * @param params The parameters
- * @return Value
- */
-static Value do_exec(zval **object, zval *method, int argc, zval ***params)
-{
- // the return zval
- zval *retval = nullptr;
-
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // the current exception
- zval *oldException = EG(exception);
-
- // call the function
- if (call_user_function_ex(CG(function_table), object, method, &retval, argc, params, 1, NULL TSRMLS_CC) != SUCCESS)
- {
- // throw an exception, the function does not exist
- throw Exception("Invalid call to "+Value(method).stringValue());
-
- // unreachable, but let's return at least something to prevent compiler warnings
- return nullptr;
- }
- else
- {
- // was an exception thrown inside the function? In that case we throw a C++ new exception
- // to give the C++ code the chance to catch it
- if (oldException != EG(exception) && EG(exception)) throw OrigException(EG(exception) TSRMLS_CC);
-
- // no (additional) exception was thrown
- return retval ? Value(retval) : nullptr;
- }
-}
-
-/**
- * Call function with a number of parameters
- * @param argc Number of parameters
- * @param argv The parameters
- * @return Value
- */
-Value Value::exec(int argc, zval ***params) const
-{
- // call helper function
- return do_exec(nullptr, _val, argc, params);
-}
-
-/**
- * Call method with a number of parameters
- * @param name Name of method to call
- * @param argc Number of parameters
- * @param argv The parameters
- * @return Value
- */
-Value Value::exec(const char *name, int argc, struct _zval_struct ***params)
-{
- // wrap the name in a Php::Value object to get a zval
- Value method(name);
-
- // call helper function
- return do_exec(&_val, method._val, argc, params);
-}
-
-/**
- * The type of object
- * @return Type
- */
-Type Value::type() const
-{
- // return regular type
- return (Type)Z_TYPE_P(_val);
-}
-
-/**
- * Change the internal type
- * @param type
- * @return Value
- */
-Value &Value::setType(Type type)
-{
- // skip if nothing changes
- if (this->type() == type) return *this;
-
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // run the conversion
- switch (type) {
- case Type::Null: convert_to_null(_val); break;
- case Type::Numeric: convert_to_long(_val); break;
- case Type::Float: convert_to_double(_val); break;
- case Type::Bool: convert_to_boolean(_val); break;
- case Type::Array: convert_to_array(_val); break;
- case Type::Object: convert_to_object(_val); break;
- case Type::String: convert_to_string(_val); break;
- case Type::Resource: throw Php::Exception("Resource types can not be handled by the PHP-CPP library"); break;
- case Type::Constant: throw Php::Exception("Constant types can not be assigned to a PHP-CPP library variable"); break;
- case Type::ConstantArray: throw Php::Exception("Constant types can not be assigned to a PHP-CPP library variable"); break;
- case Type::Callable: throw Php::Exception("Callable types can not be assigned to a PHP-CPP library variable"); break;
- }
-
- // done
- return *this;
-}
-
-/**
- * Check if the variable holds something that is callable
- * @return bool
- */
-bool Value::isCallable() const
-{
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // we can not rely on the type, because strings can be callable as well
- return zend_is_callable(_val, 0, NULL TSRMLS_CC);
-}
-
-/**
- * Make a clone of the type
- * @return Value
- */
-Value Value::clone() const
-{
- // the zval that will hold the copy
- zval *copy;
-
- // allocate memory
- ALLOC_ZVAL(copy);
-
- // copy the data
- INIT_PZVAL_COPY(copy, _val);
-
- // run the copy constructor to ensure that everything gets copied
- zval_copy_ctor(copy);
-
- // done
- return Value(copy);
-}
-
-/**
- * Clone the zval to a different type
- * @param type
- * @return Value
- */
-Value Value::clone(Type type) const
-{
- // regular clone if nothing changes
- if (this->type() == type) return clone();
-
- // make a clone
- return clone().setType(type);
-}
-
-/**
- * Retrieve the value as integer
- * @return long
- */
-int64_t Value::numericValue() const
-{
- // already a long?
- if (isNumeric()) return Z_LVAL_P(_val);
-
- // make a clone
- return clone(Type::Numeric).numericValue();
-}
-
-/**
- * Retrieve the value as boolean
- * @return bool
- */
-bool Value::boolValue() const
-{
- // already a bool?
- if (isBool()) return Z_BVAL_P(_val);
-
- // make a clone
- return clone(Type::Bool).boolValue();
-}
-
-/**
- * Retrieve the value as string
- * @return string
- */
-std::string Value::stringValue() const
-{
- // already a string?
- if (isString()) return std::string(Z_STRVAL_P(_val), Z_STRLEN_P(_val));
-
- // make a clone
- return clone(Type::String).stringValue();
-}
-
-/**
- * Access to the raw buffer
- * @return char *
- */
-char *Value::buffer() const
-{
- // must be a string
- if (!isString()) return nullptr;
-
- // already a string?
- return Z_STRVAL_P(_val);
-}
-
-/**
- * Reserve enough space
- * @param size
- * @return char*
- */
-char *Value::reserve(size_t size)
-{
- // must be a string
- setType(Type::String);
-
- // is the current buffer too small?
- if (Z_STRLEN_P(_val) < (int)size)
- {
- // is there already a buffer?
- if (!Z_STRVAL_P(_val)) Z_STRVAL_P(_val) = (char *)emalloc(size+1);
-
- // reallocate an existing buffer
- else Z_STRVAL_P(_val) = (char *)erealloc(Z_STRVAL_P(_val), size+1);
-
- // last byte should be zero
- Z_STRVAL_P(_val)[size] = 0;
- }
-
- // store size
- Z_STRLEN_P(_val) = size;
-
- // done
- return Z_STRVAL_P(_val);
-}
-
-/**
- * Access to the raw buffer
- * @return const char *
- */
-const char *Value::rawValue() const
-{
- // must be a string
- if (isString()) return Z_STRVAL_P(_val);
-
- // make a clone and return that buffer
- return clone(Type::String).rawValue();
-}
-
-/**
- * Retrieve the value as decimal
- * @return double
- */
-double Value::floatValue() const
-{
- // already a double
- if (isFloat()) return Z_DVAL_P(_val);
-
- // make a clone
- return clone(Type::Float).floatValue();
-}
-
-/**
- * The number of members in case of an array or object
- * @return int
- */
-int Value::size() const
-{
- // is it an array?
- if (isArray())
- {
- // get the number of elements
- return zend_hash_num_elements(Z_ARRVAL_P(_val));
- }
-
- // or an object?
- else if (isObject())
- {
- // the count_elements member function should be defined
- if (!Z_OBJ_HT_P(_val)->count_elements) return 0;
-
- // create a variable to hold the result
- long result;
-
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // call the function
- return Z_OBJ_HT_P(_val)->count_elements(_val, &result TSRMLS_CC) == SUCCESS ? result : 0;
- }
-
- // not an array, return string size if this is a string
- else if (isString())
- {
- // get string size
- return Z_STRLEN_P(_val);
- }
-
- // in all other situations, we convert the variable to a string
- else
- {
- // make a copy
- Value copy(*this);
-
- // convert the copy to a string
- copy.setType(Type::String);
-
- // return the string size
- return copy.size();
- }
-}
-
-/**
- * Convert the object to a map with string index and Php::Value value
- * @return std::map
- */
-std::map<std::string,Php::Value> Value::mapValue() const
-{
- // result variable
- std::map<std::string,Php::Value> result;
-
- // iterate over the object
- for (auto &iter : *this) result[iter.first.rawValue()] = iter.second;
-
- // done
- return result;
-}
-
-/**
- * Internal helper method to retrieve an iterator
- * @param begin Should the iterator start at the begin
- * @return iterator
- */
-ValueIterator Value::createIterator(bool begin) const
-{
- // check type
- if (isArray()) return ValueIterator(new HashIterator(Z_ARRVAL_P(_val), begin));
-
- // get access to the hast table
- if (isObject())
- {
- // we need the TSRMLS_CC variable
- TSRMLS_FETCH();
-
- // is a special iterator method defined in the class entry?
- auto *entry = zend_get_class_entry(_val TSRMLS_CC);
-
- // check if there is an iterator
- if (entry->get_iterator)
- {
- // the object implements Traversable interface, we have to use a
- // special iterator to user that interface too
- return ValueIterator(new TraverseIterator(_val, begin TSRMLS_CC));
- }
- else
- {
- // construct a regular iterator
- return ValueIterator(new HashIterator(Z_OBJ_HT_P(_val)->get_properties(_val TSRMLS_CC), begin));
- }
- }
-
- // invalid
- return ValueIterator(new InvalidIterator());
-}
-
-/**
- * Return an iterator for iterating over the values
- * This is only meaningful for Value objects that hold an array or an object
- * @return iterator
- */
-ValueIterator Value::begin() const
-{
- return createIterator(true);
-}
-
-/**
- * Return an iterator for iterating over the values
- * This is only meaningful for Value objects that hold an array or an object
- * @return iterator
- */
-ValueIterator Value::end() const
-{
- return createIterator(false);
-}
-
-/**
- * Does the array contain a certain index?
- * @param index
- * @return bool
- */
-bool Value::contains(int index) const
-{
- // must be an array
- if (!isArray()) return false;
-
- // unused variable
- zval **result;
-
- // check if this index is already in the array
- return zend_hash_index_find(Z_ARRVAL_P(_val), index, (void**)&result) != FAILURE;
-}
-
-/**
- * Does the array contain a certain key
- * @param key
- * @param size
- * @return boolean
- */
-bool Value::contains(const char *key, int size) const
-{
- // calculate size
- if (size < 0) size = strlen(key);
-
- // deal with arrays
- if (isArray())
- {
- // unused variable
- zval **result;
-
- // check if index is already in the array
- return zend_hash_find(Z_ARRVAL_P(_val), key, size+1, (void **)&result) != FAILURE;
- }
- else if (isObject())
- {
- // we need the tsrmls_cc variable
- TSRMLS_FETCH();
-
- // retrieve the class entry
- auto *entry = zend_get_class_entry(_val TSRMLS_CC);
-
- // read the property (cast necessary for php 5.3)
- zval *property = zend_read_property(entry, _val, (char *)key, size, 0 TSRMLS_CC);
-
- // check if valid
- return property != nullptr;
- }
- else
- {
- // scalar variable
- return false;
- }
-}
-
-/**
- * Get access to a certain array member
- * @param index
- * @return Value
- */
-Value Value::get(int index) const
-{
- // must be an array
- if (!isArray()) return Value();
-
- // zval to retrieve
- zval **result;
-
- // check if index is in the array
- if (zend_hash_index_find(Z_ARRVAL_P(_val), index, (void **)&result) == FAILURE) return Value();
-
- // wrap the value
- return Value(*result);
-}
-
-/**
- * Get access to a certain assoc member
- * @param key
- * @param size
- * @return Value
- */
-Value Value::get(const char *key, int size) const
-{
- // must be an array
- if (!isArray() && !isObject()) return Value();
-
- // calculate size
- if (size < 0) size = strlen(key);
-
- // are we in an object or an array?
- if (isArray())
- {
- // the result value
- zval **result;
-
- // check if this index is already in the array, otherwise we return NULL
- if (zend_hash_find(Z_ARRVAL_P(_val), key, size + 1, (void **)&result) == FAILURE) return Value();
-
- // wrap the value
- return Value(*result);
- }
- else
- {
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // retrieve the class entry
- auto *entry = zend_get_class_entry(_val TSRMLS_CC);
-
- // read the property (case necessary for php 5.3)
- zval *property = zend_read_property(entry, _val, (char *)key, size, 1 TSRMLS_CC);
-
- // wrap in value
- return Value(property);
- }
-}
-
-/**
- * Set a certain property without performing any checks
- * This method can be used when it is already known that the object is an array
- * @param index
- * @param value
- * @return Value
- */
-void Value::setRaw(int index, const Value &value)
-{
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // add the value (this will decrement refcount on any current variable)
- add_index_zval(_val, index, value._val);
-
- // the variable has one more reference (the array entry)
- Z_ADDREF_P(value._val);
-}
-
-/**
- * Set a certain property
- * @param index
- * @param value
- * @return Value
- */
-void Value::set(int index, const Value &value)
-{
- // the current value
- zval **current;
-
- // check if this index is already in the array, otherwise we return NULL
- if (isArray() && zend_hash_index_find(Z_ARRVAL_P(_val), index, (void **)&current) != FAILURE)
- {
- // skip if nothing is going to change
- if (value._val == *current) return;
- }
-
- // must be an array
- setType(Type::Array);
-
- // set property
- setRaw(index, value);
-}
-
-/**
- * Set a certain property without running any checks
- * @param key
- * @param size
- * @param value
- */
-void Value::setRaw(const char *key, int size, const Value &value)
-{
- // is this an object?
- if (isObject())
- {
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // retrieve the class entry
- auto *entry = zend_get_class_entry(_val TSRMLS_CC);
-
- // update the property (cast necessary for php 5.3)
- zend_update_property(entry, _val, (char *)key, size, value._val TSRMLS_CC);
- }
- else
- {
- // if this is not a reference variable, we should detach it to implement copy on write
- SEPARATE_ZVAL_IF_NOT_REF(&_val);
-
- // add the value (this will reduce the refcount of the current value)
- add_assoc_zval_ex(_val, key, size+1, value._val);
-
- // the variable has one more reference (the array entry)
- Z_ADDREF_P(value._val);
- }
-}
-
-/**
- * Set a certain property
- * @param key
- * @param size
- * @param value
- * @return Value
- */
-void Value::set(const char *key, int size, const Value &value)
-{
- // the current value
- zval **current;
-
- // check if this index is already in the array, otherwise we return NULL
- if (isArray() && zend_hash_find(Z_ARRVAL_P(_val), key, size + 1, (void **)&current) != FAILURE)
- {
- // skip if nothing is going to change
- if (value._val == *current) return;
- }
-
- // this should be an object or an array
- if (!isObject()) setType(Type::Array);
-
- // done
- setRaw(key, size, value);
-}
-
-/**
- * Array access operator
- * This can be used for accessing arrays
- * @param index
- * @return HashMember
- */
-HashMember<int> Value::operator[](int index)
-{
- return HashMember<int>(this, index);
-}
-
-/**
- * Array access operato
- * This can be used for accessing associative arrays
- * @param key
- * @return HashMember
- */
-HashMember<std::string> Value::operator[](const std::string &key)
-{
- return HashMember<std::string>(this, key);
-}
-
-/**
- * Array access operator
- * This can be used for accessing associative arrays
- * @param key
- * @return HashMember
- */
-HashMember<std::string> Value::operator[](const char *key)
-{
- return HashMember<std::string>(this, key);
-}
-
-/**
- * Retrieve the original implementation
- *
- * This only works for classes that were implemented using PHP-CPP,
- * it returns nullptr for all other classes
- *
- * @return Base*
- */
-Base *Value::implementation() const
-{
- // must be an object
- if (!isObject()) return nullptr;
-
- // we need the tsrm_ls variable
- TSRMLS_FETCH();
-
- // retrieve the mixed object that contains the base
- return ObjectImpl::find(_val TSRMLS_CC)->object();
-}
-
-/**
- * Custom output stream operator
- * @param stream
- * @param value
- * @return ostream
- */
-std::ostream &operator<<(std::ostream &stream, const Value &value)
-{
- return stream << value.stringValue();
-}
-
-/**
- * End of namespace
- */
-}
-
diff --git a/src/valueiterator.cpp b/src/valueiterator.cpp
deleted file mode 100644
index 65c687c..0000000
--- a/src/valueiterator.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/**
- * ValueIterator.cpp
- *
- * Implementation of the value iterator
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-#include "includes.h"
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Copy constructor
- * @param that
- * @param tsrm_ls
- */
-ValueIterator::ValueIterator(const ValueIterator &that) : _impl(that._impl->clone()) {}
-
-/**
- * Destructor
- */
-ValueIterator::~ValueIterator()
-{
- // get rid of implementation
- delete _impl;
-}
-
-/**
- * Increment position
- * @return ValueIterator
- */
-ValueIterator &ValueIterator::operator++()
-{
- // increment implementation
- _impl->increment();
-
- // done
- return *this;
-}
-
-/**
- * Decrement position
- * @return ValueIterator
- */
-ValueIterator &ValueIterator::operator--()
-{
- // decrement implementation
- _impl->decrement();
-
- // done
- return *this;
-}
-
-/**
- * Compare with other iterator
- * @param that
- * @return bool
- */
-bool ValueIterator::operator==(const ValueIterator &that) const
-{
- return _impl->equals(that._impl);
-}
-
-/**
- * Compare with other iterator
- * @param that
- * @return bool
- */
-bool ValueIterator::operator!=(const ValueIterator &that) const
-{
- return !_impl->equals(that._impl);
-}
-
-/**
- * Derefecence, this returns a std::pair with the current key and value
- * @return std::pair
- */
-const std::pair<Value,Value> &ValueIterator::operator*() const
-{
- return _impl->current();
-}
-
-/**
- * Dereference, this returns a std::pair with the current key and value
- * @return std::pair
- */
-const std::pair<Value,Value> *ValueIterator::operator->() const
-{
- return &_impl->current();
-}
-
-/**
- * End namespace
- */
-}
-
diff --git a/src/valueiteratorimpl.h b/src/valueiteratorimpl.h
deleted file mode 100644
index 82c888d..0000000
--- a/src/valueiteratorimpl.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * ValueIteratorImpl.h
- *
- * Interface that describes what an implementation of a value iterator should
- * look like. This is an internal class that extension developers do not
- * need. It is used internally inside the ValueIterator class.
- *
- * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
- * @copyright 2014 Copernica BV
- */
-
-/**
- * Set up namespace
- */
-namespace Php {
-
-/**
- * Class definition
- */
-class ValueIteratorImpl
-{
-public:
- /**
- * Constructor
- */
- ValueIteratorImpl() {}
-
- /**
- * Destructor
- */
- virtual ~ValueIteratorImpl() {}
-
- /**
- * Clone the object
- * @param tsrm_ls
- * @return ValueIteratorImpl*
- */
- virtual ValueIteratorImpl *clone() = 0;
-
- /**
- * Increment position (pre-increment)
- * @param tsrm_ls
- * @return bool
- */
- virtual bool increment() = 0;
-
- /**
- * Decrement position (pre-decrement)
- * @return bool
- */
- virtual bool decrement() = 0;
-
- /**
- * Compare with other iterator
- * @param that
- * @return bool
- */
- virtual bool equals(const ValueIteratorImpl *that) const = 0;
-
- /**
- * Derefecence, this returns a std::pair with the current key and value
- * @return std::pair
- */
- virtual const std::pair<Value,Value> &current() const = 0;
-};
-
-/**
- * End namespace
- */
-}
-