}
/* }}} */
+static void populate_subpat_array(
+ zval *subpats, char *subject, PCRE2_SIZE *offsets, char **subpat_names, int count, const PCRE2_SPTR mark, zend_long flags) {
+ zend_bool offset_capture = (flags & PREG_OFFSET_CAPTURE) != 0;
+ zend_bool unmatched_as_null = (flags & PREG_UNMATCHED_AS_NULL) != 0;
+ int i;
+ if (subpat_names) {
+ if (offset_capture) {
+ for (i = 0; i < count; i++) {
+ add_offset_pair(subpats, subject + offsets[i<<1],
+ offsets[(i<<1)+1] - offsets[i<<1],
+ offsets[i<<1], subpat_names[i], unmatched_as_null);
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ if (subpat_names[i]) {
+ if (PCRE2_UNSET == offsets[i<<1]) {
+ if (unmatched_as_null) {
+ add_assoc_null(subpats, subpat_names[i]);
+ } else {
+ add_assoc_str(subpats, subpat_names[i], ZSTR_EMPTY_ALLOC());
+ }
+ } else {
+ add_assoc_stringl(subpats, subpat_names[i], subject + offsets[i<<1],
+ offsets[(i<<1)+1] - offsets[i<<1]);
+ }
+ }
+ if (PCRE2_UNSET == offsets[i<<1]) {
+ if (unmatched_as_null) {
+ add_next_index_null(subpats);
+ } else {
+ add_next_index_str(subpats, ZSTR_EMPTY_ALLOC());
+ }
+ } else {
+ add_next_index_stringl(subpats, subject + offsets[i<<1],
+ offsets[(i<<1)+1] - offsets[i<<1]);
+ }
+ }
+ }
+ } else {
+ if (offset_capture) {
+ for (i = 0; i < count; i++) {
+ add_offset_pair(subpats, subject + offsets[i<<1],
+ offsets[(i<<1)+1] - offsets[i<<1],
+ offsets[i<<1], NULL, unmatched_as_null);
+ }
+ } else {
+ for (i = 0; i < count; i++) {
+ if (PCRE2_UNSET == offsets[i<<1]) {
+ if (unmatched_as_null) {
+ add_next_index_null(subpats);
+ } else {
+ add_next_index_str(subpats, ZSTR_EMPTY_ALLOC());
+ }
+ } else {
+ add_next_index_stringl(subpats, subject + offsets[i<<1],
+ offsets[(i<<1)+1] - offsets[i<<1]);
+ }
+ }
+ }
+ }
+ /* Add MARK, if available */
+ if (mark) {
+ add_assoc_string_ex(subpats, "MARK", sizeof("MARK") - 1, (char *)mark);
+ }
+}
+
static void php_do_pcre_match(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ */
{
/* parameters */
}
}
} else {
- /* Allocate the result set array */
+ /* Allocate and populate the result set array */
array_init_size(&result_set, count + (mark ? 1 : 0));
-
- /* Add all the subpatterns to it */
- if (subpat_names) {
- if (offset_capture) {
- for (i = 0; i < count; i++) {
- add_offset_pair(&result_set, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1], offsets[i<<1], subpat_names[i], unmatched_as_null);
- }
- } else {
- for (i = 0; i < count; i++) {
- if (subpat_names[i]) {
- if (PCRE2_UNSET == offsets[i<<1]) {
- if (unmatched_as_null) {
- add_assoc_null(&result_set, subpat_names[i]);
- } else {
- add_assoc_str(&result_set, subpat_names[i], ZSTR_EMPTY_ALLOC());
- }
- } else {
- add_assoc_stringl(&result_set, subpat_names[i], subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1]);
- }
- }
- if (PCRE2_UNSET == offsets[i<<1]) {
- if (unmatched_as_null) {
- add_next_index_null(&result_set);
- } else {
- add_next_index_str(&result_set, ZSTR_EMPTY_ALLOC());
- }
- } else {
- add_next_index_stringl(&result_set, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1]);
- }
- }
- }
- } else {
- if (offset_capture) {
- for (i = 0; i < count; i++) {
- add_offset_pair(&result_set, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1], offsets[i<<1], NULL, unmatched_as_null);
- }
- } else {
- for (i = 0; i < count; i++) {
- if (PCRE2_UNSET == offsets[i<<1]) {
- if (unmatched_as_null) {
- add_next_index_null(&result_set);
- } else {
- add_next_index_str(&result_set, ZSTR_EMPTY_ALLOC());
- }
- } else {
- add_next_index_stringl(&result_set, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1]);
- }
- }
- }
- }
- /* Add MARK, if available */
mark = pcre2_get_mark(match_data);
- if (mark) {
- add_assoc_string_ex(&result_set, "MARK", sizeof("MARK") - 1, (char *)mark);
- }
+ populate_subpat_array(
+ &result_set, subject, offsets, subpat_names, count, mark, flags);
/* And add it to the output array */
zend_hash_next_index_insert(Z_ARRVAL_P(subpats), &result_set);
}
} else { /* single pattern matching */
/* For each subpattern, insert it into the subpatterns array. */
- if (subpat_names) {
- if (offset_capture) {
- for (i = 0; i < count; i++) {
- add_offset_pair(subpats, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1],
- offsets[i<<1], subpat_names[i], unmatched_as_null);
- }
- } else {
- for (i = 0; i < count; i++) {
- if (subpat_names[i]) {
- if (PCRE2_UNSET == offsets[i<<1]) {
- if (unmatched_as_null) {
- add_assoc_null(subpats, subpat_names[i]);
- } else {
- add_assoc_str(subpats, subpat_names[i], ZSTR_EMPTY_ALLOC());
- }
- } else {
- add_assoc_stringl(subpats, subpat_names[i], subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1]);
- }
- }
- if (PCRE2_UNSET == offsets[i<<1]) {
- if (unmatched_as_null) {
- add_next_index_null(subpats);
- } else {
- add_next_index_str(subpats, ZSTR_EMPTY_ALLOC());
- }
- } else {
- add_next_index_stringl(subpats, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1]);
- }
- }
- }
- } else {
- if (offset_capture) {
- for (i = 0; i < count; i++) {
- add_offset_pair(subpats, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1],
- offsets[i<<1], NULL, unmatched_as_null);
- }
- } else {
- for (i = 0; i < count; i++) {
- if (PCRE2_UNSET == offsets[i<<1]) {
- if (unmatched_as_null) {
- add_next_index_null(subpats);
- } else {
- add_next_index_str(subpats, ZSTR_EMPTY_ALLOC());
- }
- } else {
- add_next_index_stringl(subpats, subject + offsets[i<<1],
- offsets[(i<<1)+1] - offsets[i<<1]);
- }
- }
- }
- }
- /* Add MARK, if available */
mark = pcre2_get_mark(match_data);
- if (mark) {
- add_assoc_string_ex(subpats, "MARK", sizeof("MARK") - 1, (char *)mark);
- }
+ populate_subpat_array(
+ subpats, subject, offsets, subpat_names, count, mark, flags);
break;
}
}
/* {{{ preg_do_repl_func
*/
-static zend_string *preg_do_repl_func(zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *subject, PCRE2_SIZE *offsets, char **subpat_names, int count, const PCRE2_SPTR mark)
+static zend_string *preg_do_repl_func(zend_fcall_info *fci, zend_fcall_info_cache *fcc, char *subject, PCRE2_SIZE *offsets, char **subpat_names, int count, const PCRE2_SPTR mark, zend_long flags)
{
zend_string *result_str;
zval retval; /* Function return value */
zval arg; /* Argument to pass to function */
- int i;
array_init_size(&arg, count + (mark ? 1 : 0));
- if (subpat_names) {
- for (i = 0; i < count; i++) {
- if (subpat_names[i]) {
- add_assoc_stringl(&arg, subpat_names[i], &subject[offsets[i<<1]] , offsets[(i<<1)+1] - offsets[i<<1]);
- }
- add_next_index_stringl(&arg, &subject[offsets[i<<1]], offsets[(i<<1)+1] - offsets[i<<1]);
- }
- } else {
- for (i = 0; i < count; i++) {
- add_next_index_stringl(&arg, &subject[offsets[i<<1]], offsets[(i<<1)+1] - offsets[i<<1]);
- }
- }
- if (mark) {
- add_assoc_string(&arg, "MARK", (char *) mark);
- }
+ populate_subpat_array(&arg, subject, offsets, subpat_names, count, mark, flags);
fci->retval = &retval;
fci->param_count = 1;
/* }}} */
/* {{{ php_pcre_replace_func_impl() */
-static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_string *subject_str, char *subject, size_t subject_len, zend_fcall_info *fci, zend_fcall_info_cache *fcc, size_t limit, size_t *replace_count)
+static zend_string *php_pcre_replace_func_impl(pcre_cache_entry *pce, zend_string *subject_str, char *subject, size_t subject_len, zend_fcall_info *fci, zend_fcall_info_cache *fcc, size_t limit, size_t *replace_count, zend_long flags)
{
uint32_t options; /* Execution options */
int count; /* Count of matched subpatterns */
/* Use custom function to get replacement string and its length. */
eval_result = preg_do_repl_func(fci, fcc, subject, offsets, subpat_names, count,
- pcre2_get_mark(match_data));
+ pcre2_get_mark(match_data), flags);
ZEND_ASSERT(eval_result);
new_len = zend_safe_address_guarded(1, ZSTR_LEN(eval_result), new_len);
static zend_always_inline zend_string *php_pcre_replace_func(zend_string *regex,
zend_string *subject_str,
zend_fcall_info *fci, zend_fcall_info_cache *fcc,
- size_t limit, size_t *replace_count)
+ size_t limit, size_t *replace_count, zend_long flags)
{
pcre_cache_entry *pce; /* Compiled regular expression */
zend_string *result; /* Function result */
return NULL;
}
pce->refcount++;
- result = php_pcre_replace_func_impl(pce, subject_str, ZSTR_VAL(subject_str), ZSTR_LEN(subject_str), fci, fcc,
- limit, replace_count);
+ result = php_pcre_replace_func_impl(
+ pce, subject_str, ZSTR_VAL(subject_str), ZSTR_LEN(subject_str), fci, fcc,
+ limit, replace_count, flags);
pce->refcount--;
return result;
/* {{{ php_replace_in_subject_func
*/
-static zend_string *php_replace_in_subject_func(zval *regex, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *subject, size_t limit, size_t *replace_count)
+static zend_string *php_replace_in_subject_func(zval *regex, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *subject, size_t limit, size_t *replace_count, zend_long flags)
{
zend_string *result;
zend_string *subject_str = zval_get_string(subject);
if (Z_TYPE_P(regex) != IS_ARRAY) {
- result = php_pcre_replace_func(Z_STR_P(regex),
- subject_str,
- fci, fcc,
- limit,
- replace_count);
+ result = php_pcre_replace_func(
+ Z_STR_P(regex), subject_str, fci, fcc, limit, replace_count, flags);
zend_string_release_ex(subject_str, 0);
return result;
} else {
/* Do the actual replacement and put the result back into subject_str
for further replacements. */
- result = php_pcre_replace_func(regex_str,
- subject_str,
- fci, fcc,
- limit,
- replace_count);
+ result = php_pcre_replace_func(
+ regex_str, subject_str, fci, fcc, limit, replace_count, flags);
zend_tmp_string_release(tmp_regex_str);
zend_string_release_ex(subject_str, 0);
subject_str = result;
/* {{{ preg_replace_func_impl
*/
-static size_t preg_replace_func_impl(zval *return_value, zval *regex, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *subject, zend_long limit_val)
+static size_t preg_replace_func_impl(zval *return_value, zval *regex, zend_fcall_info *fci, zend_fcall_info_cache *fcc, zval *subject, zend_long limit_val, zend_long flags)
{
zend_string *result;
size_t replace_count = 0;
}
if (Z_TYPE_P(subject) != IS_ARRAY) {
- result = php_replace_in_subject_func(regex, fci, fcc, subject, limit_val, &replace_count);
+ result = php_replace_in_subject_func(
+ regex, fci, fcc, subject, limit_val, &replace_count, flags);
if (result != NULL) {
RETVAL_STR(result);
} else {
/* For each subject entry, convert it to string, then perform replacement
and add the result to the return_value array. */
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(subject), num_key, string_key, subject_entry) {
- result = php_replace_in_subject_func(regex, fci, fcc, subject_entry, limit_val, &replace_count);
+ result = php_replace_in_subject_func(
+ regex, fci, fcc, subject_entry, limit_val, &replace_count, flags);
if (result != NULL) {
/* Add to return array */
ZVAL_STR(&zv, result);
static PHP_FUNCTION(preg_replace_callback)
{
zval *regex, *replace, *subject, *zcount = NULL;
- zend_long limit = -1;
+ zend_long limit = -1, flags = 0;
size_t replace_count;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
/* Get function parameters and do error-checking. */
- ZEND_PARSE_PARAMETERS_START(3, 5)
+ ZEND_PARSE_PARAMETERS_START(3, 6)
Z_PARAM_ZVAL(regex)
Z_PARAM_ZVAL(replace)
Z_PARAM_ZVAL(subject)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(limit)
Z_PARAM_ZVAL(zcount)
+ Z_PARAM_LONG(flags)
ZEND_PARSE_PARAMETERS_END();
if (!zend_is_callable_ex(replace, NULL, 0, NULL, &fcc, NULL)) {
fci.object = NULL;
ZVAL_COPY_VALUE(&fci.function_name, replace);
- replace_count = preg_replace_func_impl(return_value, regex, &fci, &fcc, subject, limit);
+ replace_count = preg_replace_func_impl(return_value, regex, &fci, &fcc, subject, limit, flags);
if (zcount) {
ZEND_TRY_ASSIGN_LONG(zcount, replace_count);
}
static PHP_FUNCTION(preg_replace_callback_array)
{
zval regex, zv, *replace, *subject, *pattern, *zcount = NULL;
- zend_long limit = -1;
+ zend_long limit = -1, flags = 0;
zend_string *str_idx;
size_t replace_count = 0;
zend_fcall_info fci;
zend_fcall_info_cache fcc;
/* Get function parameters and do error-checking. */
- ZEND_PARSE_PARAMETERS_START(2, 4)
+ ZEND_PARSE_PARAMETERS_START(2, 5)
Z_PARAM_ARRAY(pattern)
Z_PARAM_ZVAL(subject)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(limit)
Z_PARAM_ZVAL(zcount)
+ Z_PARAM_LONG(flags)
ZEND_PARSE_PARAMETERS_END();
fci.size = sizeof(fci);
ZVAL_COPY_VALUE(&fci.function_name, replace);
- replace_count += preg_replace_func_impl(&zv, ®ex, &fci, &fcc, subject, limit);
+ replace_count += preg_replace_func_impl(&zv, ®ex, &fci, &fcc, subject, limit, flags);
if (subject != return_value) {
subject = return_value;
} else {
ZEND_ARG_INFO(0, subject)
ZEND_ARG_INFO(0, limit)
ZEND_ARG_INFO(1, count)
+ ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_replace_callback_array, 0, 0, 2)
ZEND_ARG_INFO(0, subject)
ZEND_ARG_INFO(0, limit)
ZEND_ARG_INFO(1, count)
+ ZEND_ARG_INFO(0, flags)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_preg_split, 0, 0, 2)