New extract feature
| From: | Jan Lehnardt | Date: | Sun, 30 Jun 2002 16:08:20 +0000 |
| Subject: | New extract feature | ||
| Groups: | php.dev | ||
| Request: | Send a blank email to php-dev+get-85682@lists.php.net to get a copy of this message | ||
Hi,
the attached patch enables extract() to take user defined callback function
to process the extracted variable names. It also fixes a minor WS problem I
introduced before.
Example:
<?php
$array = array('a' => 'huhu', 'b' => 'haha');
function extract_func($s, $p, $b)
{
return (( $b ) ? $p:"my__").$s;
}
extract($array);
extract($array,EXTR_USER_FUNC,'extract_func',array("pref",true));
var_dump($a);
var_dump($b);
var_dump($my__a);
var_dump($my__b);
var_dump($prefa);
var_dump($prefb);
?>
I like the patch to be reviewd before I commit it, thank you.
Jan
--
Q: Thank Jan? A: http://geschenke.an.dasmoped.net/
Index: ext/standard/array.c =================================================================== RCS file: /repository/php4/ext/standard/array.c,v retrieving revision 1.167 diff -u -r1.167 array.c --- ext/standard/array.c 18 Jun 2002 13:16:33 -0000 1.167 +++ ext/standard/array.c 30 Jun 2002 16:02:41 -0000 @@ -55,23 +55,24 @@ #define EXTR_OVERWRITE 0 #define EXTR_SKIP 1 #define EXTR_PREFIX_SAME 2 -#define EXTR_PREFIX_ALL 3 -#define EXTR_PREFIX_INVALID 4 -#define EXTR_PREFIX_IF_EXISTS 5 -#define EXTR_IF_EXISTS 6 - -#define SORT_REGULAR 0 -#define SORT_NUMERIC 1 -#define SORT_STRING 2 +#define EXTR_PREFIX_ALL 3 +#define EXTR_PREFIX_INVALID 4 +#define EXTR_PREFIX_IF_EXISTS 5 +#define EXTR_IF_EXISTS 6 +#define EXTR_USER_FUNC 7 + +#define SORT_REGULAR 0 +#define SORT_NUMERIC 1 +#define SORT_STRING 2 -#define SORT_DESC 3 -#define SORT_ASC 4 +#define SORT_DESC 3 +#define SORT_ASC 4 -#define CASE_LOWER 0 -#define CASE_UPPER 1 +#define CASE_LOWER 0 +#define CASE_UPPER 1 -#define COUNT_NORMAL 0 -#define COUNT_RECURSIVE 1 +#define COUNT_NORMAL 0 +#define COUNT_RECURSIVE 1 PHP_MINIT_FUNCTION(array) { @@ -86,6 +87,7 @@ REGISTER_LONG_CONSTANT("EXTR_PREFIX_INVALID", EXTR_PREFIX_INVALID, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("EXTR_PREFIX_IF_EXISTS", EXTR_PREFIX_IF_EXISTS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("EXTR_IF_EXISTS", EXTR_IF_EXISTS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("EXTR_USER_FUNC", EXTR_USER_FUNC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_ASC", SORT_ASC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_DESC", SORT_DESC, CONST_CS | CONST_PERSISTENT); @@ -1130,17 +1132,18 @@ } -/* {{{ proto int extract(array var_array [, int extract_type [, string prefix]]) +/* {{{ proto int extract(array var_array [, int extract_type [, string prefix [, array arguments]]]) Imports variables into symbol table from an array */ PHP_FUNCTION(extract) { zval **var_array, **z_extract_type, **prefix; zval **entry, *data; + zval **user_func_res, **user_func_params, **args[99], *user_func_name; char *var_name; smart_str final_name = {0}; ulong num_key; uint var_name_len; - int var_exists, extract_type, key_type, count = 0; + int var_exists, extract_type, key_type, count = 0, argc, i = 1, user_func_params_flag = 0; HashPosition pos; switch (ZEND_NUM_ARGS()) { @@ -1170,7 +1173,29 @@ } convert_to_long_ex(z_extract_type); extract_type = Z_LVAL_PP(z_extract_type); - convert_to_string_ex(prefix); + if ((Z_TYPE_PP(prefix) == IS_ARRAY) && (extract_type == EXTR_USER_FUNC)) { + convert_to_array_ex(prefix); + } else { + convert_to_string_ex(prefix); + } + + break; + + case 4: + if (zend_get_parameters_ex(4, &var_array, &z_extract_type, &prefix, &user_func_params) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(z_extract_type); + extract_type = Z_LVAL_PP(z_extract_type); + if (Z_TYPE_PP(prefix) == IS_ARRAY) { + convert_to_array_ex(prefix); + } else { + convert_to_string_ex(prefix); + } + SEPARATE_ZVAL(user_func_params); + convert_to_array_ex(user_func_params); + + user_func_params_flag = 1; break; default: @@ -1178,7 +1203,7 @@ break; } - if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) { + if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_USER_FUNC) { php_error(E_WARNING, "Unknown extract type in call to %s()", get_active_function_name(TSRMLS_C)); return; @@ -1189,7 +1214,7 @@ get_active_function_name(TSRMLS_C)); return; } - + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(var_array), &pos); while(zend_hash_get_current_data_ex(Z_ARRVAL_PP(var_array), (void **)&entry, &pos) == SUCCESS) { key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(var_array), &var_name, &var_name_len, &num_key, 0, &pos); @@ -1248,6 +1273,51 @@ } break; + case EXTR_USER_FUNC: + if (final_name.len == 0) { + if (!user_func_params_flag) { /* the user specified no additional arguments */ + argc = 1; + args[0] = emalloc(sizeof(args[0])); + MAKE_STD_ZVAL(*args[0]); + ZVAL_STRINGL(*args[0], var_name, var_name_len, 0); + } else { /* we have an array of additional arguments */ + argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(user_func_params)); + args[0] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*args[0]); + ZVAL_STRINGL(*args[0], var_name, var_name_len, 0); + + /* copy arguments from user-array to zval **args[] */ + for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(user_func_params)); + zend_hash_get_current_data(Z_ARRVAL_PP(user_func_params), (void **)&args[i++]) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_PP(user_func_params))) + { + args[i] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*args[i]); + + } + } + + user_func_res = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*user_func_res); + + /* Call the userland function */ + if (call_user_function_ex(EG(function_table), NULL, *prefix, + user_func_res, argc, args, 0, NULL TSRMLS_CC) == SUCCESS) { + + smart_str_appendl(&final_name, Z_STRVAL_PP(user_func_res), Z_STRLEN_PP(user_func_res)); + zval_ptr_dtor(user_func_res); + + + } else { + zval_ptr_dtor(user_func_res); + efree(args); + php_error(E_WARNING, "Unable to call %s() - function does not exist", + Z_STRVAL_PP(prefix)); + } + efree(*args); + } + break; + default: if (!var_exists) smart_str_appendl(&final_name, var_name, var_name_len);
Index: ext/standard/array.c =================================================================== RCS file: /repository/php4/ext/standard/array.c,v retrieving revision 1.167 diff -u -r1.167 array.c --- ext/standard/array.c 18 Jun 2002 13:16:33 -0000 1.167 +++ ext/standard/array.c 30 Jun 2002 16:02:41 -0000 @@ -55,23 +55,24 @@ #define EXTR_OVERWRITE 0 #define EXTR_SKIP 1 #define EXTR_PREFIX_SAME 2 -#define EXTR_PREFIX_ALL 3 -#define EXTR_PREFIX_INVALID 4 -#define EXTR_PREFIX_IF_EXISTS 5 -#define EXTR_IF_EXISTS 6 - -#define SORT_REGULAR 0 -#define SORT_NUMERIC 1 -#define SORT_STRING 2 +#define EXTR_PREFIX_ALL 3 +#define EXTR_PREFIX_INVALID 4 +#define EXTR_PREFIX_IF_EXISTS 5 +#define EXTR_IF_EXISTS 6 +#define EXTR_USER_FUNC 7 + +#define SORT_REGULAR 0 +#define SORT_NUMERIC 1 +#define SORT_STRING 2 -#define SORT_DESC 3 -#define SORT_ASC 4 +#define SORT_DESC 3 +#define SORT_ASC 4 -#define CASE_LOWER 0 -#define CASE_UPPER 1 +#define CASE_LOWER 0 +#define CASE_UPPER 1 -#define COUNT_NORMAL 0 -#define COUNT_RECURSIVE 1 +#define COUNT_NORMAL 0 +#define COUNT_RECURSIVE 1 PHP_MINIT_FUNCTION(array) { @@ -86,6 +87,7 @@ REGISTER_LONG_CONSTANT("EXTR_PREFIX_INVALID", EXTR_PREFIX_INVALID, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("EXTR_PREFIX_IF_EXISTS", EXTR_PREFIX_IF_EXISTS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("EXTR_IF_EXISTS", EXTR_IF_EXISTS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("EXTR_USER_FUNC", EXTR_USER_FUNC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_ASC", SORT_ASC, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SORT_DESC", SORT_DESC, CONST_CS | CONST_PERSISTENT); @@ -1130,17 +1132,18 @@ } -/* {{{ proto int extract(array var_array [, int extract_type [, string prefix]]) +/* {{{ proto int extract(array var_array [, int extract_type [, string prefix [, array arguments]]]) Imports variables into symbol table from an array */ PHP_FUNCTION(extract) { zval **var_array, **z_extract_type, **prefix; zval **entry, *data; + zval **user_func_res, **user_func_params, **args[99], *user_func_name; char *var_name; smart_str final_name = {0}; ulong num_key; uint var_name_len; - int var_exists, extract_type, key_type, count = 0; + int var_exists, extract_type, key_type, count = 0, argc, i = 1, user_func_params_flag = 0; HashPosition pos; switch (ZEND_NUM_ARGS()) { @@ -1170,7 +1173,29 @@ } convert_to_long_ex(z_extract_type); extract_type = Z_LVAL_PP(z_extract_type); - convert_to_string_ex(prefix); + if ((Z_TYPE_PP(prefix) == IS_ARRAY) && (extract_type == EXTR_USER_FUNC)) { + convert_to_array_ex(prefix); + } else { + convert_to_string_ex(prefix); + } + + break; + + case 4: + if (zend_get_parameters_ex(4, &var_array, &z_extract_type, &prefix, &user_func_params) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_long_ex(z_extract_type); + extract_type = Z_LVAL_PP(z_extract_type); + if (Z_TYPE_PP(prefix) == IS_ARRAY) { + convert_to_array_ex(prefix); + } else { + convert_to_string_ex(prefix); + } + SEPARATE_ZVAL(user_func_params); + convert_to_array_ex(user_func_params); + + user_func_params_flag = 1; break; default: @@ -1178,7 +1203,7 @@ break; } - if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_IF_EXISTS) { + if (extract_type < EXTR_OVERWRITE || extract_type > EXTR_USER_FUNC) { php_error(E_WARNING, "Unknown extract type in call to %s()", get_active_function_name(TSRMLS_C)); return; @@ -1189,7 +1214,7 @@ get_active_function_name(TSRMLS_C)); return; } - + zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(var_array), &pos); while(zend_hash_get_current_data_ex(Z_ARRVAL_PP(var_array), (void **)&entry, &pos) == SUCCESS) { key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(var_array), &var_name, &var_name_len, &num_key, 0, &pos); @@ -1248,6 +1273,51 @@ } break; + case EXTR_USER_FUNC: + if (final_name.len == 0) { + if (!user_func_params_flag) { /* the user specified no additional arguments */ + argc = 1; + args[0] = emalloc(sizeof(args[0])); + MAKE_STD_ZVAL(*args[0]); + ZVAL_STRINGL(*args[0], var_name, var_name_len, 0); + } else { /* we have an array of additional arguments */ + argc = 1 + zend_hash_num_elements(Z_ARRVAL_PP(user_func_params)); + args[0] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*args[0]); + ZVAL_STRINGL(*args[0], var_name, var_name_len, 0); + + /* copy arguments from user-array to zval **args[] */ + for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(user_func_params)); + zend_hash_get_current_data(Z_ARRVAL_PP(user_func_params), (void **)&args[i++]) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_PP(user_func_params))) + { + args[i] = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*args[i]); + + } + } + + user_func_res = emalloc(sizeof(zval *)); + MAKE_STD_ZVAL(*user_func_res); + + /* Call the userland function */ + if (call_user_function_ex(EG(function_table), NULL, *prefix, + user_func_res, argc, args, 0, NULL TSRMLS_CC) == SUCCESS) { + + smart_str_appendl(&final_name, Z_STRVAL_PP(user_func_res), Z_STRLEN_PP(user_func_res)); + zval_ptr_dtor(user_func_res); + + + } else { + zval_ptr_dtor(user_func_res); + efree(args); + php_error(E_WARNING, "Unable to call %s() - function does not exist", + Z_STRVAL_PP(prefix)); + } + efree(*args); + } + break; + default: if (!var_exists) smart_str_appendl(&final_name, var_name, var_name_len);