]> granicus.if.org Git - php/commitdiff
- Add convenience function zend_is_callable_ex() and base zend_is_callable
authorMarcus Boerger <helly@php.net>
Thu, 28 Jul 2005 20:55:50 +0000 (20:55 +0000)
committerMarcus Boerger <helly@php.net>
Thu, 28 Jul 2005 20:55:50 +0000 (20:55 +0000)
  and zend_make_callable on it. This functions allows to check if a php
  variable is a callable function and returns its function pointer as well
  as object if possible.
# Commit this now so we can use it in 5.1.* series as discussed with Andi.

Zend/zend_API.c
Zend/zend_API.h

index 109c5f3223e2bdec561ddfeebcc707163f44eb35..752ca290b8a62caa6583c2d541f9521af94f66c6 100644 (file)
@@ -1905,23 +1905,38 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_
        return 1;
 }
 
-ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name)
+ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_function **fptr_ptr, zval ***zobj_ptr_ptr TSRMLS_DC)
 {
        char *lcname;
-       zend_bool retval = 0;
-       TSRMLS_FETCH();
+       zend_bool retval = 0; 
+       int callable_name_len_local;
+       zend_function *fptr_local;
+       zval **zobj_ptr_local;
+
+       if (callable_name_len == NULL) {
+               callable_name_len = &callable_name_len_local;
+       }
+       if (fptr_ptr == NULL) {
+               fptr_ptr = &fptr_local;
+       }
+       if (zobj_ptr_ptr == NULL) {
+               zobj_ptr_ptr = &zobj_ptr_local;
+       }
+       *fptr_ptr = NULL;
+       *zobj_ptr_ptr = NULL;
 
        switch (Z_TYPE_P(callable)) {
                case IS_STRING:
                        if (callable_name) {
                                *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
+                               *callable_name_len = Z_STRLEN_P(callable);
                        }
                        if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
                                return 1;
                        }
 
                        lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
-                       if (zend_hash_exists(EG(function_table), lcname, Z_STRLEN_P(callable)+1)) {
+                       if (zend_hash_find(EG(function_table), lcname, Z_STRLEN_P(callable)+1, (void**)fptr_ptr) == SUCCESS) {
                                retval = 1;
                        }
                        efree(lcname);
@@ -1932,7 +1947,6 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
                                zval **method;
                                zval **obj;
                                zend_class_entry *ce = NULL, **pce;
-                               zend_uint callable_name_len;
                                
                                if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2 &&
                                        zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj) == SUCCESS &&
@@ -1944,14 +1958,14 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
                                                if (callable_name) {
                                                        char *ptr;
 
-                                                       callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::");
-                                                       ptr = *callable_name = emalloc(callable_name_len);
+                                                       *callable_name_len = Z_STRLEN_PP(obj) + Z_STRLEN_PP(method) + sizeof("::") - 1;
+                                                       ptr = *callable_name = emalloc(*callable_name_len + 1);
                                                        memcpy(ptr, Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
                                                        ptr += Z_STRLEN_PP(obj);
                                                        memcpy(ptr, "::", sizeof("::") - 1);
                                                        ptr += sizeof("::") - 1;
                                                        memcpy(ptr, Z_STRVAL_PP(method), Z_STRLEN_PP(method) + 1);
-                                               }
+                                                                                               }
 
                                                if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY)
                                                        return 1;
@@ -1969,12 +1983,14 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
                                                efree(lcname);
                                        } else {
                                                ce = Z_OBJCE_PP(obj); /* TBFixed: what if it's overloaded? */
+                                               
+                                               *zobj_ptr_ptr = obj;
 
                                                if (callable_name) {
                                                        char *ptr;
 
-                                                       callable_name_len = ce->name_length + Z_STRLEN_PP(method) + sizeof("::");
-                                                       ptr = *callable_name = emalloc(callable_name_len);
+                                                       *callable_name_len = ce->name_length + Z_STRLEN_PP(method) + sizeof("::") - 1;
+                                                       ptr = *callable_name = emalloc(*callable_name_len + 1);
                                                        memcpy(ptr, ce->name, ce->name_length);
                                                        ptr += ce->name_length;
                                                        memcpy(ptr, "::", sizeof("::") - 1);
@@ -2003,6 +2019,13 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
                                                                        }
                                                                }
                                                        }
+                                                       if (retval) {
+                                                               if ((check_flags & IS_CALLABLE_CHECK_IS_STATIC) != 0 && (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0) {
+                                                                       retval = 0;
+                                                               } else {
+                                                                       *fptr_ptr = fbc;
+                                                               }
+                                                       }
                                                }
                                                /* check for __call too */
                                                if (retval == 0 && ce->__call != 0) {
@@ -2012,6 +2035,7 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
                                        }
                                } else if (callable_name) {
                                        *callable_name = estrndup("Array", sizeof("Array")-1);
+                                       *callable_name_len = sizeof("Array") - 1;
                                }
                        }
                        break;
@@ -2023,6 +2047,7 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
 
                                zend_make_printable_zval(callable, &expr_copy, &use_copy);
                                *callable_name = estrndup(Z_STRVAL(expr_copy), Z_STRLEN(expr_copy));
+                               *callable_name_len = Z_STRLEN(expr_copy);
                                zval_dtor(&expr_copy);
                        }
                        break;
@@ -2032,6 +2057,14 @@ ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **cal
 }
 
 
+ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name)
+{
+       TSRMLS_FETCH();
+
+       return zend_is_callable_ex(callable, check_flags, callable_name, NULL, NULL, NULL TSRMLS_CC);
+}
+
+
 ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC)
 {
        char *lcname, *func, *class_name;
@@ -2039,7 +2072,7 @@ ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRML
        zend_class_entry **pce;
        int class_name_len;
 
-       if (zend_is_callable(callable, 0, callable_name)) {
+       if (zend_is_callable_ex(callable, 0, callable_name, NULL, NULL, NULL TSRMLS_CC)) {
                return 1;
        }
        switch (Z_TYPE_P(callable)) {
index e28fa1b7c681b69ad22d085645fa35a21aca3073..8e914d80b395ad890950af6b8c0c045e5433e435 100644 (file)
@@ -196,7 +196,9 @@ ZEND_API void zend_wrong_param_count(TSRMLS_D);
 
 #define IS_CALLABLE_CHECK_SYNTAX_ONLY (1<<0)
 #define IS_CALLABLE_CHECK_NO_ACCESS   (1<<1)
+#define IS_CALLABLE_CHECK_IS_STATIC   (1<<2)
 
+ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_function **fptr_ptr, zval ***zobj_ptr_ptr TSRMLS_DC);
 ZEND_API zend_bool zend_is_callable(zval *callable, uint check_flags, char **callable_name);
 ZEND_API zend_bool zend_make_callable(zval *callable, char **callable_name TSRMLS_DC);
 ZEND_API char *zend_get_module_version(char *module_name);