summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandot <mabingyao@gmail.com>2014-07-10 13:06:22 +0800
committerandot <mabingyao@gmail.com>2014-07-10 13:06:22 +0800
commitb6cc95e9a96edf3a1733c4f562d42eed79dd8946 (patch)
treeb3e8e711ec17ef33699c1d2679da9560d7cf93c4
parent28578382589dab25ea5fbd35b7754687706abc07 (diff)
Add Php::is_a implementation.
Add is, isSubClassOf for Php::Value. Add Php::is_a implementation. Add Php::is_subclass_of implementation.
-rw-r--r--include/fastcall.h18
-rw-r--r--include/value.h21
-rw-r--r--phpcpp.h3
-rw-r--r--zend/includes.h1
-rw-r--r--zend/value.cpp38
5 files changed, 80 insertions, 1 deletions
diff --git a/include/fastcall.h b/include/fastcall.h
new file mode 100644
index 0000000..778a9b2
--- /dev/null
+++ b/include/fastcall.h
@@ -0,0 +1,18 @@
+/**
+ * fastcall.h
+ *
+ * This file holds some PHP functions implementation in C directly.
+ *
+ */
+
+namespace Php {
+
+ inline bool is_a(const Value &obj, const std::string classname, bool allow_string = false) {
+ return obj.is(classname, allow_string);
+ }
+ inline bool is_subclass_of(const Value &obj, const std::string classname, bool allow_string = true) {
+ return obj.isSubClassOf(classname, allow_string);
+ }
+
+}
+
diff --git a/include/value.h b/include/value.h
index f72304c..b3c288c 100644
--- a/include/value.h
+++ b/include/value.h
@@ -965,7 +965,28 @@ public:
return dynamic_cast<T*>(base);
}
+ /**
+ * Checks if this object is of the class or has the class as one of its parents
+ * @param classname
+ * @param allow_string
+ * @return bool
+ */
+ inline bool is(const std::string &classname, bool allow_string=false) const {
+ return isImpl(classname, allow_string, false);
+ }
+
+ /**
+ * Checks if this object has the class as one of its parents
+ * @param classname
+ * @return bool
+ */
+ inline bool isSubClassOf(const std::string &classname, bool allow_string=true) const {
+ return isImpl(classname, allow_string, true);
+ }
+
private:
+
+ bool isImpl(const std::string &classname, bool allow_string, bool only_subclass) const;
/**
* Call function with a number of parameters
* @param argc Number of parameters
diff --git a/phpcpp.h b/phpcpp.h
index c3f3365..8be1a25 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -2,7 +2,7 @@
* phpcpp.h
*
* Library to build PHP extensions with CPP
- *
+ *
* @copyright 2013 CopernicA BV
* @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
*/
@@ -60,6 +60,7 @@
#include <phpcpp/namespace.h>
#include <phpcpp/extension.h>
#include <phpcpp/call.h>
+#include <phpcpp/fastcall.h>
/**
* Macro to export a function
diff --git a/zend/includes.h b/zend/includes.h
index 63b435e..8af557c 100644
--- a/zend/includes.h
+++ b/zend/includes.h
@@ -79,6 +79,7 @@
#include "../include/namespace.h"
#include "../include/extension.h"
#include "../include/call.h"
+#include "../include/fastcall.h"
/**
* Common header files for internal use only
diff --git a/zend/value.cpp b/zend/value.cpp
index 9a1a5db..38a0425 100644
--- a/zend/value.cpp
+++ b/zend/value.cpp
@@ -1408,6 +1408,44 @@ bool Value::isCallable() const
return zend_is_callable(_val, 0, NULL TSRMLS_CC);
}
+bool Value::isImpl(const std::string &classname, bool allow_string, bool only_subclass) const {
+ /*
+ * allow_string - is default is false, isSubclassOf is true.
+ * if it's allowed, the the autoloader will be called if the class does not exist.
+ * default behaviour is different, as 'is' used to be used to test mixed return
+ * values and there is no easy way to deprecate this.
+ */
+ // we need the tsrm_ls variable
+ TSRMLS_FETCH();
+
+ zend_class_entry *instance_ce;
+ zend_class_entry **ce;
+
+ if (allow_string && isString()) {
+ zend_class_entry **the_ce;
+ if (zend_lookup_class(Z_STRVAL_P(_val), Z_STRLEN_P(_val), &the_ce TSRMLS_CC) == FAILURE) {
+ return false;
+ }
+ instance_ce = *the_ce;
+ }
+ else if (isObject() && HAS_CLASS_ENTRY(*_val)) {
+ instance_ce = Z_OBJCE_P(_val);
+ }
+ else {
+ return false;
+ }
+
+ if (zend_lookup_class_ex(classname.c_str(), (int32_t)classname.length(), NULL, 0, &ce TSRMLS_CC) == FAILURE) {
+ return false;
+ }
+
+ if (only_subclass && instance_ce == *ce) {
+ return false;
+ }
+
+ return instanceof_function(instance_ce, *ce TSRMLS_CC);
+}
+
/**
* Make a clone of the type
* @return Value