} else
break;
} else {
- pcre_handle_exec_error(count TSRMLS_CC);
+ pcre_handle_exec_error(count);
break;
}
-
+
/* If we have matched an empty string, mimic what Perl's /g options does.
- This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
+ This turns out to be rather cunning. First we set PCRE_NOTEMPTY_ATSTART and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
- g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
+ g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0;
-
+
/* Advance to the position right after the last full match */
start_offset = offsets[1];
} while (global);
}
*walkbuf = '\0';
/* increment the result length by how much we've added to the string */
- *result_len += walkbuf - (result + *result_len);
+ result_len += (int)(walkbuf - (ZSTR_VAL(result) + result_len));
+ } else {
+ /* Use custom function to get replacement string and its length. */
+ eval_result = preg_do_repl_func(replace_val, subject, offsets, subpat_names, count, mark);
+ ZEND_ASSERT(eval_result);
+ new_len += (int)ZSTR_LEN(eval_result);
+ if (new_len >= alloc_len) {
+ alloc_len = alloc_len + 2 * new_len;
+ if (result == NULL) {
+ result = zend_string_alloc(alloc_len, 0);
+ } else {
+ result = zend_string_extend(result, alloc_len, 0);
+ }
+ }
+ /* copy the part of the string before the match */
+ memcpy(ZSTR_VAL(result) + result_len, piece, match-piece);
+ result_len += (int)(match-piece);
+
+ /* copy replacement and backrefs */
+ walkbuf = ZSTR_VAL(result) + result_len;
+
+ /* If using custom function, copy result to the buffer and clean up. */
+ memcpy(walkbuf, ZSTR_VAL(eval_result), ZSTR_LEN(eval_result));
+ result_len += (int)ZSTR_LEN(eval_result);
+ zend_string_release(eval_result);
}
- if (limit != -1)
+ if (EXPECTED(limit)) {
limit--;
-
- } else if (count == PCRE_ERROR_NOMATCH || limit == 0) {
+ }
+ } else if (count == PCRE_ERROR_NOMATCH || UNEXPECTED(limit == 0)) {
- /* If we previously set PCRE_NOTEMPTY after a null match,
+ /* If we previously set PCRE_NOTEMPTY_ATSTART after a null match,
this is not necessarily the end. We need to advance
the start offset, and continue. Fudge the offset values
to achieve this, unless we're already at the end of the string. */
break;
}
} else {
- pcre_handle_exec_error(count TSRMLS_CC);
- efree(result);
- result = NULL;
+ pcre_handle_exec_error(count);
+ if (result) {
+ zend_string_free(result);
+ result = NULL;
+ }
break;
}
-
+
/* If we have matched an empty string, mimic what Perl's /g options does.
- This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
+ This turns out to be rather cunning. First we set PCRE_NOTEMPTY_ATSTART and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
- g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
+ g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0;
-
+
/* Advance to the next piece. */
start_offset = offsets[1];
}
}
/* If we have matched an empty string, mimic what Perl's /g options does.
- This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
+ This turns out to be rather cunning. First we set PCRE_NOTEMPTY_ATSTART and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
- g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
+ g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0;
-
+
/* Advance to the position right after the last full match */
start_offset = offsets[1];
}