mirror of
https://github.com/php/php-src.git
synced 2024-11-24 18:34:21 +08:00
Merge branch 'rfc-preg-replace-callback-array' of https://github.com/zxcvdavid/php-src
Conflicts: Zend/zend_vm_gen.php ext/pcre/php_pcre.c
This commit is contained in:
commit
c524dd6d1e
@ -1353,37 +1353,16 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub
|
||||
|
||||
/* {{{ preg_replace_impl
|
||||
*/
|
||||
static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_replace, int is_filter)
|
||||
static void preg_replace_impl(zval *return_value, int argc, zval *regex, zval *replace, zval *subject, zend_long limit, zval *zcount, int is_callable_replace, int is_filter)
|
||||
{
|
||||
zval *regex,
|
||||
*replace,
|
||||
*subject,
|
||||
*subject_entry,
|
||||
*zcount = NULL;
|
||||
zval *subject_entry;
|
||||
int limit_val = -1;
|
||||
zend_long limit = -1;
|
||||
zend_string *result;
|
||||
zend_string *string_key;
|
||||
zend_ulong num_key;
|
||||
zend_string *callback_name;
|
||||
int replace_count=0, old_replace_count;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
/* Get function parameters and do error-checking. */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(3, 5)
|
||||
Z_PARAM_ZVAL(regex)
|
||||
Z_PARAM_ZVAL(replace)
|
||||
Z_PARAM_ZVAL(subject)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(limit)
|
||||
Z_PARAM_ZVAL_EX(zcount, 0, 1)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
if (!is_callable_replace && Z_TYPE_P(replace) == IS_ARRAY && Z_TYPE_P(regex) != IS_ARRAY) {
|
||||
php_error_docref(NULL, E_WARNING, "Parameter mismatch, pattern is a string while replacement is an array");
|
||||
RETURN_FALSE;
|
||||
@ -1403,7 +1382,7 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
zend_string_release(callback_name);
|
||||
}
|
||||
|
||||
if (ZEND_NUM_ARGS() > 3) {
|
||||
if (argc > 3) {
|
||||
limit_val = (int)limit;
|
||||
}
|
||||
|
||||
@ -1433,7 +1412,8 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
}
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
} else { /* if subject is not an array */
|
||||
} else {
|
||||
/* if subject is not an array */
|
||||
old_replace_count = replace_count;
|
||||
if ((result = php_replace_in_subject(regex, replace, subject, limit_val, is_callable_replace, &replace_count)) != NULL) {
|
||||
if (!is_filter || replace_count > old_replace_count) {
|
||||
@ -1443,11 +1423,10 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ZEND_NUM_ARGS() > 4) {
|
||||
if (argc > 4) {
|
||||
zval_dtor(zcount);
|
||||
ZVAL_LONG(zcount, replace_count);
|
||||
}
|
||||
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1455,7 +1434,26 @@ static void preg_replace_impl(INTERNAL_FUNCTION_PARAMETERS, int is_callable_repl
|
||||
Perform Perl-style regular expression replacement. */
|
||||
static PHP_FUNCTION(preg_replace)
|
||||
{
|
||||
preg_replace_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
|
||||
zval *regex, *replace, *subject, *zcount = NULL;
|
||||
zend_long limit = -1;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
/* Get function parameters and do error-checking. */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(3, 5)
|
||||
Z_PARAM_ZVAL(regex)
|
||||
Z_PARAM_ZVAL(replace)
|
||||
Z_PARAM_ZVAL(subject)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(limit)
|
||||
Z_PARAM_ZVAL_EX(zcount, 0, 1)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
preg_replace_impl(return_value, ZEND_NUM_ARGS(), regex, replace, subject, limit, zcount, 0, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1463,7 +1461,84 @@ static PHP_FUNCTION(preg_replace)
|
||||
Perform Perl-style regular expression replacement using replacement callback. */
|
||||
static PHP_FUNCTION(preg_replace_callback)
|
||||
{
|
||||
preg_replace_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
|
||||
zval *regex, *replace, *subject, *zcount = NULL;
|
||||
zend_long limit = -1;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
/* Get function parameters and do error-checking. */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(3, 5)
|
||||
Z_PARAM_ZVAL(regex)
|
||||
Z_PARAM_ZVAL(replace)
|
||||
Z_PARAM_ZVAL(subject)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(limit)
|
||||
Z_PARAM_ZVAL_EX(zcount, 0, 1)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
preg_replace_impl(return_value, ZEND_NUM_ARGS(), regex, replace, subject, limit, zcount, 1, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ proto mixed preg_replace_callback_array(array pattern, mixed subject [, int limit [, int &count]])
|
||||
Perform Perl-style regular expression replacement using replacement callback. */
|
||||
static PHP_FUNCTION(preg_replace_callback_array)
|
||||
{
|
||||
zval regex, tmp_ret, *replace, *subject, *pattern, *zcount = NULL;
|
||||
zend_long limit = -1;
|
||||
zend_ulong num_idx, count = 0;
|
||||
zend_string *str_idx;
|
||||
int argc;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
/* Get function parameters and do error-checking. */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "az|lz/", &pattern, &subject, &limit, &zcount) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(2, 4)
|
||||
Z_PARAM_ARRAY(pattern)
|
||||
Z_PARAM_ZVAL(subject)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(limit)
|
||||
Z_PARAM_ZVAL_EX(zcount, 0, 1)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
argc = ZEND_NUM_ARGS();
|
||||
|
||||
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(pattern), num_idx, str_idx, replace) {
|
||||
if (str_idx) {
|
||||
ZVAL_STR_COPY(®ex, str_idx);
|
||||
} else {
|
||||
php_error_docref(NULL, E_WARNING, "Delimiter must not be alphanumeric or backslash");
|
||||
zval_dtor(return_value);
|
||||
ZVAL_COPY(return_value, subject);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Z_ISNULL_P(return_value)) {
|
||||
preg_replace_impl(&tmp_ret, argc + 1, ®ex, replace, subject, limit, zcount, 1, 0);
|
||||
} else {
|
||||
preg_replace_impl(&tmp_ret, argc + 1, ®ex, replace, return_value, limit, zcount, 1, 0);
|
||||
zval_ptr_dtor(return_value);
|
||||
}
|
||||
|
||||
if (zcount && Z_TYPE_P(zcount) == IS_LONG) {
|
||||
count += Z_LVAL_P(zcount);
|
||||
}
|
||||
|
||||
ZVAL_COPY_VALUE(return_value, &tmp_ret);
|
||||
zval_ptr_dtor(®ex);
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
|
||||
if (zcount && Z_TYPE_P(zcount) == IS_LONG) {
|
||||
zval_dtor(zcount);
|
||||
ZVAL_LONG(zcount, count);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1471,7 +1546,26 @@ static PHP_FUNCTION(preg_replace_callback)
|
||||
Perform Perl-style regular expression replacement and only return matches. */
|
||||
static PHP_FUNCTION(preg_filter)
|
||||
{
|
||||
preg_replace_impl(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
|
||||
zval *regex, *replace, *subject, *zcount = NULL;
|
||||
zend_long limit = -1;
|
||||
|
||||
#ifndef FAST_ZPP
|
||||
/* Get function parameters and do error-checking. */
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzz|lz/", ®ex, &replace, &subject, &limit, &zcount) == FAILURE) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ZEND_PARSE_PARAMETERS_START(3, 5)
|
||||
Z_PARAM_ZVAL(regex)
|
||||
Z_PARAM_ZVAL(replace)
|
||||
Z_PARAM_ZVAL(subject)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(limit)
|
||||
Z_PARAM_ZVAL_EX(zcount, 0, 1)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
#endif
|
||||
|
||||
preg_replace_impl(return_value, ZEND_NUM_ARGS(), regex, replace, subject, limit, zcount, 0, 1);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -1953,6 +2047,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_replace_callback, 0, 0, 3)
|
||||
ZEND_ARG_INFO(1, count)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_replace_callback_array, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, pattern)
|
||||
ZEND_ARG_INFO(0, subject)
|
||||
ZEND_ARG_INFO(0, limit)
|
||||
ZEND_ARG_INFO(1, count)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_split, 0, 0, 2)
|
||||
ZEND_ARG_INFO(0, pattern)
|
||||
ZEND_ARG_INFO(0, subject)
|
||||
@ -1980,6 +2081,7 @@ static const zend_function_entry pcre_functions[] = {
|
||||
PHP_FE(preg_match_all, arginfo_preg_match_all)
|
||||
PHP_FE(preg_replace, arginfo_preg_replace)
|
||||
PHP_FE(preg_replace_callback, arginfo_preg_replace_callback)
|
||||
PHP_FE(preg_replace_callback_array, arginfo_preg_replace_callback_array)
|
||||
PHP_FE(preg_filter, arginfo_preg_replace)
|
||||
PHP_FE(preg_split, arginfo_preg_split)
|
||||
PHP_FE(preg_quote, arginfo_preg_quote)
|
||||
|
39
ext/pcre/tests/preg_replace_callback_array.phpt
Normal file
39
ext/pcre/tests/preg_replace_callback_array.phpt
Normal file
@ -0,0 +1,39 @@
|
||||
--TEST--
|
||||
preg_replace_callback_array()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function f() {
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
try {
|
||||
var_dump(preg_replace_callback_array(array('/\w/' => 'f'), 'z'));
|
||||
} catch(Exception $e) {}
|
||||
|
||||
function g($x) {
|
||||
return "'$x[0]'";
|
||||
}
|
||||
|
||||
var_dump(preg_replace_callback_array(array('@\b\w{1,2}\b@' => 'g'), array('a b3 bcd', 'v' => 'aksfjk', 12 => 'aa bb')));
|
||||
|
||||
var_dump(preg_replace_callback_array(array('~\A.~' => 'g'), array(array('xyz'))));
|
||||
|
||||
var_dump(preg_replace_callback_array(array('~\A.~' => create_function('$m', 'return strtolower($m[0]);')), 'ABC'));
|
||||
?>
|
||||
--EXPECTF--
|
||||
array(3) {
|
||||
[0]=>
|
||||
string(12) "'a' 'b3' bcd"
|
||||
["v"]=>
|
||||
string(6) "aksfjk"
|
||||
[12]=>
|
||||
string(9) "'aa' 'bb'"
|
||||
}
|
||||
|
||||
Notice: Array to string conversion in %spreg_replace_callback_array.php on line %d
|
||||
array(1) {
|
||||
[0]=>
|
||||
string(7) "'A'rray"
|
||||
}
|
||||
string(3) "aBC"
|
40
ext/pcre/tests/preg_replace_callback_array2.phpt
Normal file
40
ext/pcre/tests/preg_replace_callback_array2.phpt
Normal file
@ -0,0 +1,40 @@
|
||||
--TEST--
|
||||
preg_replace_callback_array() 2
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
var_dump(preg_replace_callback_array());
|
||||
var_dump(preg_replace_callback_array(1));
|
||||
var_dump(preg_replace_callback_array(1,2));
|
||||
var_dump(preg_replace_callback_array(1,2,3));
|
||||
$a = 5;
|
||||
var_dump(preg_replace_callback_array(1,2,3,$a));
|
||||
$a = "";
|
||||
var_dump(preg_replace_callback_array(array("" => ""),"","",$a));
|
||||
$a = array();
|
||||
var_dump(preg_replace_callback($a,$a,$a,$a));
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTF--
|
||||
Warning: preg_replace_callback_array() expects at least 2 parameters, 0 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: preg_replace_callback_array() expects at least 2 parameters, 1 given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: preg_replace_callback_array() expects parameter 1 to be array, integer given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: preg_replace_callback_array() expects parameter 1 to be array, integer given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: preg_replace_callback_array() expects parameter 1 to be array, integer given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: preg_replace_callback_array() expects parameter 3 to be integer, string given in %s on line %d
|
||||
NULL
|
||||
|
||||
Warning: preg_replace_callback() expects parameter 4 to be integer, array given in %s on line %d
|
||||
NULL
|
||||
Done
|
39
ext/pcre/tests/preg_replace_callback_array3.phpt
Normal file
39
ext/pcre/tests/preg_replace_callback_array3.phpt
Normal file
@ -0,0 +1,39 @@
|
||||
--TEST--
|
||||
preg_replace_callback_array() 3
|
||||
--FILE--
|
||||
<?php
|
||||
$code = "test-EXECUTE_DATA-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER";
|
||||
|
||||
$code = preg_replace_callback_array(
|
||||
array(
|
||||
"/EXECUTE_DATA/m" => function($matches) { return "execute_data";},
|
||||
"/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER_EX/m" => function($matches) { return "helper_ex"; },
|
||||
),
|
||||
$code);
|
||||
|
||||
var_dump($code);
|
||||
$code = array("test-EXECUTE_DATA-ZEND_VM_DISPATCH_TO_HELPER_EX-test",
|
||||
"test-sdf-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER_EX-test-EXECUTE_DATA-test");
|
||||
|
||||
$code = preg_replace_callback_array(
|
||||
array(
|
||||
"/EXECUTE_DATA/m" => function($matches) { return "execute_data";},
|
||||
"/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
|
||||
),
|
||||
$code, -1, $count);
|
||||
|
||||
var_dump($code, $count);
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(31) "test-execute_data-xcvxcv-helper"
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(32) "test-execute_data-helper_EX-test"
|
||||
[1]=>
|
||||
string(48) "test-sdf-xcvxcv-helper_EX-test-execute_data-test"
|
||||
}
|
||||
int(4)
|
40
ext/pcre/tests/preg_replace_callback_array4.phpt
Normal file
40
ext/pcre/tests/preg_replace_callback_array4.phpt
Normal file
@ -0,0 +1,40 @@
|
||||
--TEST--
|
||||
preg_replace_callback_array() 4
|
||||
--FILE--
|
||||
<?php
|
||||
$code = "test-EXECUTE_DATA-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER";
|
||||
|
||||
$code = preg_replace_callback_array(
|
||||
array(
|
||||
"/EXECUTE_DATA/m" => function($matches) { return "execute_data";},
|
||||
"/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER_EX/m" => function($matches) { return "helper_ex"; },
|
||||
),
|
||||
$code);
|
||||
|
||||
var_dump($code);
|
||||
$code = array("test-EXECUTE_DATA-ZEND_VM_DISPATCH_TO_HELPER_EX-test",
|
||||
"test-sdf-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER_EX-test-EXECUTE_DATA-test");
|
||||
|
||||
$code = preg_replace_callback_array(
|
||||
array(
|
||||
"/ZEND_VM_DISPATCH_TO_HANDLER/m" => function($matches) { return "handler"; },
|
||||
23234 => function($matches) { return "execute_data";},
|
||||
"/ZEND_VM_DISPATCH_TO_HELPER/m" => function($matches) { return "helper"; },
|
||||
),
|
||||
$code, -1, $count);
|
||||
|
||||
var_dump($code, $count);
|
||||
?>
|
||||
--EXPECTF--
|
||||
string(31) "test-execute_data-xcvxcv-helper"
|
||||
|
||||
Warning: preg_replace_callback_array(): Delimiter must not be alphanumeric or backslash in %s on line %d
|
||||
array(2) {
|
||||
[0]=>
|
||||
string(52) "test-EXECUTE_DATA-ZEND_VM_DISPATCH_TO_HELPER_EX-test"
|
||||
[1]=>
|
||||
string(68) "test-sdf-xcvxcv-ZEND_VM_DISPATCH_TO_HELPER_EX-test-EXECUTE_DATA-test"
|
||||
}
|
||||
int(0)
|
@ -97,6 +97,15 @@ string(%d) "Extension [ <persistent> extension #%d pcre version <no_version> ] {
|
||||
Parameter #4 [ <optional> &$count ]
|
||||
}
|
||||
}
|
||||
Function [ <internal:pcre> preg_replace_callback_array ] {
|
||||
|
||||
- Parameters [4] {
|
||||
Parameter #0 [ <required> $pattern ]
|
||||
Parameter #1 [ <required> $subject ]
|
||||
Parameter #2 [ <optional> $limit ]
|
||||
Parameter #3 [ <optional> &$count ]
|
||||
}
|
||||
}
|
||||
Function [ <internal:pcre> function preg_filter ] {
|
||||
|
||||
- Parameters [5] {
|
||||
|
Loading…
Reference in New Issue
Block a user