diff options
author | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-07-26 15:37:59 +0200 |
---|---|---|
committer | Emiel Bruijntjes <emiel.bruijntjes@copernica.com> | 2014-07-26 15:37:59 +0200 |
commit | 542e8a44708668001e59cf08b61c642da5080825 (patch) | |
tree | 8e9abf3fbd3cee887cbc096c76daea1be4b99027 | |
parent | 4104abb21a40fa0057c488199769b24519aa1da7 (diff) | |
parent | b6cc95e9a96edf3a1733c4f562d42eed79dd8946 (diff) |
Merge branch 'is_a' of https://github.com/andot/PHP-CPP
-rw-r--r-- | include/fastcall.h | 18 | ||||
-rw-r--r-- | include/value.h | 21 | ||||
-rw-r--r-- | phpcpp.h | 3 | ||||
-rw-r--r-- | zend/includes.h | 1 | ||||
-rw-r--r-- | zend/value.cpp | 38 |
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 @@ -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 352e90d..9b409f7 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 |