summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-02 11:33:53 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-02 11:33:53 +0100
commit52fe0c39457421e075959179ee6b64a20b96f0d9 (patch)
treee6dd000114d104bf6286d74682feb694b3cb97a3 /src
parentfa02aa127d2c4261d15123829e44f6d997444abc (diff)
types are not a C++11 class, introduced FixedValue class that can not change type, and implemented both Object and Array to make use of that type, implemented - but not yet tested - Base::value() method
Diffstat (limited to 'src')
-rw-r--r--src/argument.cpp4
-rw-r--r--src/base.cpp14
-rw-r--r--src/callable.cpp2
-rw-r--r--src/callable.h2
-rw-r--r--src/classbase.cpp53
-rw-r--r--src/includes.h3
-rw-r--r--src/mixedobject.h10
-rw-r--r--src/value.cpp30
8 files changed, 75 insertions, 43 deletions
diff --git a/src/argument.cpp b/src/argument.cpp
index e8e7c8a..080bf79 100644
--- a/src/argument.cpp
+++ b/src/argument.cpp
@@ -29,7 +29,7 @@ Argument::Argument(const char *name, Type type, bool required, bool byref)
_info->name = name;
_info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
- _info->type_hint = type == arrayType || type == callableType ? type : 0;
+ _info->type_hint = (unsigned char)(type == Type::Array || type == Type::Callable ? type : Type::Null);
#endif
_info->class_name = NULL;
_info->class_name_len = 0;
@@ -57,7 +57,7 @@ Argument::Argument(const char *name, const char *classname, bool nullable, bool
_info->name = name;
_info->name_len = strlen(name);
#if PHP_VERSION_ID >= 50400
- _info->type_hint = objectType;
+ _info->type_hint = (unsigned char)Type::Object;
#endif
_info->class_name = classname;
_info->class_name_len = strlen(classname);
diff --git a/src/base.cpp b/src/base.cpp
index 60e8c2d..b5f2f86 100644
--- a/src/base.cpp
+++ b/src/base.cpp
@@ -13,6 +13,20 @@
namespace Php {
/**
+ * Convert the object to a Php::Value object (how it is used externally)
+ * @return Value
+ */
+Value Base::value() const
+{
+ // because the object is stored in a MixedObject, we know that the zend_object
+ // structure is right in front of the this pointer
+ zend_object *object = (zend_object *)this - sizeof(zend_object);
+
+ // wrap the properties table, as a reference
+ return Object(*object->properties_table, true);
+}
+
+/**
* End of namespace
*/
}
diff --git a/src/callable.cpp b/src/callable.cpp
index 5745d79..66333d5 100644
--- a/src/callable.cpp
+++ b/src/callable.cpp
@@ -99,7 +99,7 @@ void Callable::initialize(zend_internal_function_info *info, const char *classna
// number of required arguments, and the expected return type
info->required_num_args = _required;
- info->_type_hint = _return;
+ info->_type_hint = (unsigned char)_return;
// we do not support return-by-reference
info->return_reference = false;
diff --git a/src/callable.h b/src/callable.h
index d08dc42..5b32558 100644
--- a/src/callable.h
+++ b/src/callable.h
@@ -94,7 +94,7 @@ protected:
* Suggestion for the return type
* @var Type
*/
- Type _return = nullType;
+ Type _return = Type::Null;
/**
* Required number of arguments
diff --git a/src/classbase.cpp b/src/classbase.cpp
index 134164d..39c8790 100644
--- a/src/classbase.cpp
+++ b/src/classbase.cpp
@@ -62,11 +62,15 @@ static zend_object_value create_object(zend_class_entry *type TSRMLS_DC)
// retrieve the classinfo object
#if PHP_VERSION_ID >= 50400
- ClassBase *info = (ClassBase *)base->info.user.doc_comment;
+ const char *comment = base->info.user.doc_comment;
#else
- ClassBase *info = *((ClassBase **)base->doc_comment);
+ const char *comment = base->doc_comment;
#endif
+ // the first byte of the comment is an empty string (null character), but
+ // the next bytes contain a pointer to the ClassInfo class
+ ClassBase *info = *((ClassBase **)(comment + 1));
+
// store the class
object->php.ce = type;
@@ -76,6 +80,7 @@ static zend_object_value create_object(zend_class_entry *type TSRMLS_DC)
// initialize the hash table
zend_hash_init(object->php.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+
// initialize the properties
#if PHP_VERSION_ID < 50399
@@ -108,6 +113,11 @@ ClassBase::~ClassBase()
{
// destruct the entries
if (_entries) delete[] _entries;
+
+ // php 5.3 deallocated the doc_comment by iself
+#if PHP_VERSION_ID >= 50400
+ if (_comment) free(_comment);
+#endif
}
/**
@@ -176,30 +186,29 @@ void ClassBase::initialize(const std::string &prefix)
// register the class
_entry = zend_register_internal_class(&entry TSRMLS_CC);
-
+
+ // 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
+ ClassBase *base = this;
+
+ // copy the 'this' pointer to the doc-comment
+ memcpy(_comment+1, &base, sizeof(ClassBase *));
+ }
+
// store pointer to the class in the unused doc_comment member
#if PHP_VERSION_ID >= 50400
- _entry->info.user.doc_comment = (const char *)this;
+ _entry->info.user.doc_comment = _comment;
#else
- /**
- * PHP 5.3 will free the doc_comment pointer if it
- * is not NULL, which will result in the classinfo
- * object being freed without being destructed
- * properly, leading to segfaults when the destruct
- * is called at a later stage (during module_shutdown).
- *
- * To prevent this we create an extra pointer that
- * points to our this pointer. We do *not* free this
- * pointer ourselves, because PHP does this. This
- * way it does not free the classinfo.
- */
- char **wrapper = (char**)malloc(sizeof(char**));
-
- // have the wrapper point to us
- *wrapper = (char *)this;
-
// and store the wrapper inside the comment
- _entry->doc_comment = (char *)wrapper;
+ _entry->doc_comment = _comment;
#endif
// set access types flags for class
diff --git a/src/includes.h b/src/includes.h
index 53dd354..c15ae93 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -47,7 +47,7 @@
*/
#include "../include/type.h"
#include "../include/value.h"
-#include "../include/array.h"
+#include "../include/forcedvalue.h"
#include "../include/hiddenpointer.h"
#include "../include/globals.h"
#include "../include/argument.h"
@@ -57,7 +57,6 @@
#include "../include/hashmember.h"
#include "../include/parameters.h"
#include "../include/modifiers.h"
-#include "../include/properties.h"
#include "../include/base.h"
#include "../include/classtype.h"
#include "../include/classbase.h"
diff --git a/src/mixedobject.h b/src/mixedobject.h
index 55a27ec..4db74da 100644
--- a/src/mixedobject.h
+++ b/src/mixedobject.h
@@ -17,7 +17,17 @@ namespace Php {
*/
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 the C++ implementation
+ * @var Base
+ */
Base *cpp;
};
diff --git a/src/value.cpp b/src/value.cpp
index 8827e6e..644e60c 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -1172,13 +1172,13 @@ Value &Value::setType(Type type)
// run the conversion
switch (type) {
- case nullType: convert_to_null(_val); break;
- case numericType: convert_to_long(_val); break;
- case floatType: convert_to_double(_val); break;
- case boolType: convert_to_boolean(_val); break;
- case arrayType: convert_to_array(_val); break;
- case objectType: convert_to_object(_val); break;
- case stringType: convert_to_string(_val); break;
+ 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;
}
// done
@@ -1241,7 +1241,7 @@ long Value::numericValue() const
if (isNumeric()) return Z_LVAL_P(_val);
// make a clone
- return clone(numericType).numericValue();
+ return clone(Type::Numeric).numericValue();
}
/**
@@ -1254,7 +1254,7 @@ bool Value::boolValue() const
if (isBool()) return Z_BVAL_P(_val);
// make a clone
- return clone(boolType).boolValue();
+ return clone(Type::Bool).boolValue();
}
/**
@@ -1267,7 +1267,7 @@ std::string Value::stringValue() const
if (isString()) return std::string(Z_STRVAL_P(_val), Z_STRLEN_P(_val));
// make a clone
- return clone(stringType).stringValue();
+ return clone(Type::String).stringValue();
}
/**
@@ -1280,7 +1280,7 @@ const char *Value::rawValue() const
if (isString()) return Z_STRVAL_P(_val);
// make a clone
- return clone(stringType).rawValue();
+ return clone(Type::String).rawValue();
}
/**
@@ -1293,7 +1293,7 @@ double Value::floatValue() const
if (isFloat()) return Z_DVAL_P(_val);
// make a clone
- return clone(floatType).floatValue();
+ return clone(Type::Float).floatValue();
}
/**
@@ -1336,7 +1336,7 @@ int Value::size() const
Value copy(*this);
// convert the copy to a string
- copy.setType(stringType);
+ copy.setType(Type::String);
// return the string size
return copy.size();
@@ -1476,7 +1476,7 @@ const Value &Value::set(int index, const Value &value)
}
// must be an array
- setType(arrayType);
+ setType(Type::Array);
// if this is not a reference variable, we should detach it to implement copy on write
SEPARATE_ZVAL_IF_NOT_REF(&_val);
@@ -1528,7 +1528,7 @@ const Value &Value::set(const char *key, int size, const Value &value)
else
{
// must be an array
- setType(arrayType);
+ setType(Type::Array);
// if this is not a reference variable, we should detach it to implement copy on write
SEPARATE_ZVAL_IF_NOT_REF(&_val);