summaryrefslogtreecommitdiff
path: root/ext/mbstring/php_mbregex.c
diff options
context:
space:
mode:
authorRui Hirokawa <hirokawa@php.net>2011-09-25 08:01:54 +0000
committerRui Hirokawa <hirokawa@php.net>2011-09-25 08:01:54 +0000
commit1297c0508a1dc88310e0f0c8297de3de732a7f67 (patch)
tree0cb332de80f1c651934daa7a74ad315e65bb5344 /ext/mbstring/php_mbregex.c
parent6d2a0bd6cc5b7ff7e1049739d16ee51042c47578 (diff)
downloadphp-git-1297c0508a1dc88310e0f0c8297de3de732a7f67.tar.gz
added mb_ereg_replace_callback().
Diffstat (limited to 'ext/mbstring/php_mbregex.c')
-rw-r--r--ext/mbstring/php_mbregex.c83
1 files changed, 74 insertions, 9 deletions
diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c
index ba71835478..dcd739937a 100644
--- a/ext/mbstring/php_mbregex.c
+++ b/ext/mbstring/php_mbregex.c
@@ -784,7 +784,7 @@ PHP_FUNCTION(mb_eregi)
/* }}} */
/* {{{ _php_mb_regex_ereg_replace_exec */
-static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options)
+static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOptionType options, int is_callable)
{
zval **arg_pattern_zval;
@@ -793,9 +793,11 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
char *replace;
int replace_len;
+ zval **arg_replace_zval;
char *string;
int string_len;
+ zval **arg_string_zval;
char *p;
php_mb_regex_t *re;
@@ -826,14 +828,20 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
char *option_str = NULL;
int option_str_len = 0;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zss|s",
- &arg_pattern_zval,
- &replace, &replace_len,
- &string, &string_len,
- &option_str, &option_str_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|s",
+ &arg_pattern_zval,
+ &arg_replace_zval,
+ &arg_string_zval,
+ &option_str, &option_str_len) == FAILURE) {
RETURN_FALSE;
}
+ replace = Z_STRVAL_PP(arg_replace_zval);
+ replace_len = Z_STRLEN_PP(arg_replace_zval);
+
+ string = Z_STRVAL_PP(arg_string_zval);
+ string_len = Z_STRLEN_PP(arg_string_zval);
+
if (option_str != NULL) {
_php_mb_regex_init_options(option_str, option_str_len, &options, &syntax, &eval);
} else {
@@ -859,7 +867,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
RETURN_FALSE;
}
- if (eval) {
+ if (eval || is_callable) {
pbuf = &eval_buf;
description = zend_make_compiled_string_description("mbregex replace" TSRMLS_CC);
} else {
@@ -867,6 +875,22 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
description = NULL;
}
+ if (is_callable) {
+ char *callback_name;
+ if (!zend_is_callable(*arg_replace_zval, 0, &callback_name TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires argument 2, '%s', to be a valid callback", callback_name);
+ efree(callback_name);
+ MAKE_COPY_ZVAL(arg_string_zval, return_value);
+ RETURN_FALSE;
+ }
+ efree(callback_name);
+
+ if (eval) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Option 'e' cannot be used with replacement callback");
+ RETURN_FALSE;
+ }
+ }
+
/* do the actual work */
err = 0;
pos = (OnigUChar *)string;
@@ -911,6 +935,8 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
i += fwd;
}
}
+
+
if (eval) {
zval v;
/* null terminate buffer */
@@ -928,7 +954,38 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
/* Clean up */
eval_buf.len = 0;
zval_dtor(&v);
+ } else if (is_callable) {
+ zval *retval_ptr;
+ zval **args[1];
+ zval *subpats;
+ int i;
+
+ MAKE_STD_ZVAL(subpats);
+ array_init(subpats);
+
+ for (i = 0; i < regs->num_regs; i++) {
+ add_next_index_stringl(subpats, string + regs->beg[i], regs->end[i] - regs->beg[i], 1);
+ }
+
+ args[0] = &subpats;
+ /* null terminate buffer */
+ smart_str_0(&eval_buf);
+
+ if (call_user_function_ex(EG(function_table), NULL, *arg_replace_zval, &retval_ptr, 1, args, 0,
+ NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
+ convert_to_string_ex(&retval_ptr);
+ smart_str_appendl(&out_buf, Z_STRVAL_P(retval_ptr), Z_STRLEN_P(retval_ptr));
+ eval_buf.len = 0;
+ zval_ptr_dtor(&retval_ptr);
+ } else {
+ efree(description);
+ if (!EG(exception)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call custom replacement function");
+ }
+ }
+ zval_ptr_dtor(&subpats);
}
+
n = regs->end[0];
if ((pos - (OnigUChar *)string) < n) {
pos = (OnigUChar *)string + n;
@@ -969,7 +1026,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
Replace regular expression for multibyte string */
PHP_FUNCTION(mb_ereg_replace)
{
- _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+ _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
}
/* }}} */
@@ -977,7 +1034,15 @@ PHP_FUNCTION(mb_ereg_replace)
Case insensitive replace regular expression for multibyte string */
PHP_FUNCTION(mb_eregi_replace)
{
- _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, ONIG_OPTION_IGNORECASE);
+ _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, ONIG_OPTION_IGNORECASE, 0);
+}
+/* }}} */
+
+/* {{{ proto string mb_ereg_replace_callback(string pattern, string callback, string string [, string option])
+ regular expression for multibyte string using replacement callback */
+PHP_FUNCTION(mb_ereg_replace_callback)
+{
+ _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
}
/* }}} */