From: Stanislav Malyshev Date: Wed, 2 Apr 2003 15:28:31 +0000 (+0000) Subject: allow class_exists() to work with namespaces too. X-Git-Tag: RELEASE_0_5~204 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=800de8acb03bcb74395e1c3afe5f87392b983451;p=php allow class_exists() to work with namespaces too. add CLASS_IS_NAMESPACE macro --- diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 2880100a5a..b70296db78 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -792,21 +792,62 @@ ZEND_FUNCTION(method_exists) } /* }}} */ +static inline zend_namespace *get_namespace_from_zval(zval **namespace_name TSRMLS_DC) +{ + zend_namespace **pns; + char *str_ns_name; + + convert_to_string_ex(namespace_name); + if(!Z_STRVAL_PP(namespace_name) || !Z_STRLEN_PP(namespace_name)) { + return EG(global_namespace_ptr); + } + + str_ns_name = estrndup(Z_STRVAL_PP(namespace_name), Z_STRLEN_PP(namespace_name)); + zend_str_tolower(str_ns_name, Z_STRLEN_PP(namespace_name)); + if(zend_hash_find(&EG(global_namespace_ptr)->class_table, str_ns_name, Z_STRLEN_PP(namespace_name)+1, (void **)&pns) == FAILURE || !CLASS_IS_NAMESPACE((*pns))) { + zend_error(E_WARNING, "Namespace '%s' is not defined!", Z_STRVAL_PP(namespace_name)); + efree(str_ns_name); + return NULL; + } + + efree(str_ns_name); + return *pns; +} -/* {{{ proto bool class_exists(string classname) +/* {{{ proto bool class_exists(string classname[, string namespace]) Checks if the class exists */ ZEND_FUNCTION(class_exists) { - zval **class_name; + zval **class_name, **namespace_name; char *lcname; + zend_namespace *ns; - if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &class_name)==FAILURE) { - ZEND_WRONG_PARAM_COUNT(); + switch(ZEND_NUM_ARGS()) { + case 0: + ZEND_WRONG_PARAM_COUNT(); + case 1: + if(zend_get_parameters_ex(1, &class_name)==FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } + ns = EG(active_namespace); + break; + case 2: + if(zend_get_parameters_ex(2, &class_name, &namespace_name)==FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } + ns = get_namespace_from_zval(namespace_name TSRMLS_CC); + if(!ns) { + RETURN_FALSE; + } + break; + default: + ZEND_WRONG_PARAM_COUNT(); } + convert_to_string_ex(class_name); lcname = estrndup((*class_name)->value.str.val, (*class_name)->value.str.len); zend_str_tolower(lcname, (*class_name)->value.str.len); - if (zend_hash_exists(EG(class_table), lcname, (*class_name)->value.str.len+1)) { + if (zend_hash_exists(&ns->class_table, lcname, (*class_name)->value.str.len+1)) { efree(lcname); RETURN_TRUE; } else { @@ -1070,33 +1111,23 @@ static int copy_class_name(zend_class_entry **pce, int num_args, va_list args, z Returns an array of all declared classes. */ ZEND_FUNCTION(get_declared_classes) { - int global_ns = 1; zval **namespace_name; - zend_namespace **pns = NULL, *ns; + zend_namespace *ns; if (ZEND_NUM_ARGS() != 0) { if(ZEND_NUM_ARGS() > 1 || zend_get_parameters_ex(1, &namespace_name)==FAILURE) { ZEND_WRONG_PARAM_COUNT(); - } else { - global_ns = 0; - convert_to_string_ex(namespace_name); - if(!Z_STRVAL_PP(namespace_name) || !Z_STRLEN_PP(namespace_name)) { - global_ns = 1; - } - } - } + } - if(!global_ns) { - zend_str_tolower(Z_STRVAL_PP(namespace_name), Z_STRLEN_PP(namespace_name)); - if(zend_hash_find(&EG(global_namespace_ptr)->class_table, Z_STRVAL_PP(namespace_name), Z_STRLEN_PP(namespace_name)+1, (void **)&pns) == FAILURE) { - zend_error(E_WARNING, "Namespace '%s' is not defined!", Z_STRVAL_PP(namespace_name)); + ns = get_namespace_from_zval(namespace_name TSRMLS_CC); + + if(!ns) { RETURN_FALSE; } - ns = *pns; } else { ns = EG(global_namespace_ptr); } - + array_init(return_value); zend_hash_apply_with_arguments(&ns->class_table, (apply_func_args_t) copy_class_name, 1, return_value); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 0522c86cb7..c11d112709 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -753,6 +753,8 @@ int zendlex(znode *zendlval TSRMLS_DC); #define ZEND_ARG_SEND_BY_REF (1<<0) #define ZEND_ARG_COMPILE_TIME_BOUND (1<<1) +#define CLASS_IS_NAMESPACE(c) ((c)->type == ZEND_INTERNAL_NAMESPACE || (c)->type == ZEND_USER_NAMESPACE) + #define AI_USE_PTR(ai) \ if ((ai).ptr_ptr) { \ (ai).ptr = *((ai).ptr_ptr); \ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index fbb8c491c2..81fae9f689 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2371,7 +2371,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS) if(retval == FAILURE) { /* try namespace */ - if(zend_hash_find(&EG(global_namespace_ptr)->class_table, class_name_strval, class_name_strlen+1, (void **)&pce) == SUCCESS && ((*pce)->type == ZEND_USER_NAMESPACE || (*pce)->type == ZEND_INTERNAL_NAMESPACE)) { + if(zend_hash_find(&EG(global_namespace_ptr)->class_table, class_name_strval, class_name_strlen+1, (void **)&pce) == SUCCESS && CLASS_IS_NAMESPACE((*pce))) { retval = SUCCESS; } } @@ -2382,7 +2382,7 @@ int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS) if(EX(opline)->extended_value == ZEND_FETCH_CLASS_GLOBAL) { ns = EG(global_namespace_ptr); } else { - if (zend_hash_find(&EG(global_namespace_ptr)->class_table, EX(opline)->op1.u.constant.value.str.val, EX(opline)->op1.u.constant.value.str.len+1, (void **)&pce) == FAILURE || ((*pce)->type != ZEND_USER_NAMESPACE && (*pce)->type != ZEND_INTERNAL_NAMESPACE)) { + if (zend_hash_find(&EG(global_namespace_ptr)->class_table, EX(opline)->op1.u.constant.value.str.val, EX(opline)->op1.u.constant.value.str.len+1, (void **)&pce) == FAILURE || !CLASS_IS_NAMESPACE((*pce))) { zend_error(E_ERROR, "Namespace '%s' not found", EX(opline)->op1.u.constant.value.str.val); } ns = *pce;