diff options
author | Dmitry Stogov <dmitry@zend.com> | 2015-02-10 13:30:25 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2015-02-10 13:30:25 +0300 |
commit | 4241a090ada5563c89d9926897b47c0411689816 (patch) | |
tree | d127982eff2be339c3c8ad5fa6b1ba8cd4e2b333 /ext/pcre | |
parent | 0be776b1fe0b00923378bfb8b9730209265a10d5 (diff) | |
download | php-git-4241a090ada5563c89d9926897b47c0411689816.tar.gz |
Avoid reallocation in preg_replace() if nothing was replaced
Diffstat (limited to 'ext/pcre')
-rw-r--r-- | ext/pcre/php_pcre.c | 39 | ||||
-rw-r--r-- | ext/pcre/php_pcre.h | 4 |
2 files changed, 29 insertions, 14 deletions
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index c255fd9174..8a6ecb5817 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -998,6 +998,7 @@ static zend_string *preg_do_repl_func(zval *function, char *subject, int *offset /* {{{ php_pcre_replace */ PHPAPI zend_string *php_pcre_replace(zend_string *regex, + zend_string *subject_str, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int limit, int *replace_count) @@ -1009,13 +1010,13 @@ PHPAPI zend_string *php_pcre_replace(zend_string *regex, return NULL; } - return php_pcre_replace_impl(pce, subject, subject_len, replace_val, + return php_pcre_replace_impl(pce, subject_str, subject, subject_len, replace_val, is_callable_replace, limit, replace_count); } /* }}} */ /* {{{ php_pcre_replace_impl() */ -PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *replace_val, +PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *subject_str, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int limit, int *replace_count) { pcre_extra *extra = pce->extra;/* Holds results of studying */ @@ -1084,8 +1085,8 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, } } - alloc_len = 2 * subject_len; - result = zend_string_alloc(alloc_len * sizeof(char), 0); + alloc_len = 0; + result = NULL; /* Initialize */ match = NULL; @@ -1148,9 +1149,17 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, } } - if (new_len > alloc_len) { - alloc_len = alloc_len + 2 * new_len; - result = zend_string_realloc(result, alloc_len, 0); + if (new_len >= alloc_len) { + if (alloc_len == 0) { + alloc_len = 2 * subject_len; + if (new_len >= alloc_len) { + alloc_len = alloc_len + 2 * new_len; + } + result = zend_string_alloc(alloc_len, 0); + } else { + alloc_len = alloc_len + 2 * new_len; + result = zend_string_realloc(result, alloc_len, 0); + } } /* copy the part of the string before the match */ memcpy(&result->val[result_len], piece, match-piece); @@ -1205,6 +1214,10 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, memcpy(&result->val[result_len], piece, 1); result_len++; } else { + if (!result && subject_str) { + result = zend_string_copy(subject_str); + break; + } new_len = result_len + subject_len - start_offset; if (new_len > alloc_len) { alloc_len = new_len; /* now we know exactly how long it is */ @@ -1214,12 +1227,15 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, memcpy(&result->val[result_len], piece, subject_len - start_offset); result_len += subject_len - start_offset; result->val[result_len] = '\0'; + result->len = result_len; break; } } else { pcre_handle_exec_error(count); - zend_string_free(result); - result = NULL; + if (result) { + zend_string_free(result); + result = NULL; + } break; } @@ -1233,9 +1249,6 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, start_offset = offsets[1]; } - if (result) { - result->len = result_len; - } if (size_offsets <= 32) { free_alloca(offsets, use_heap); } else { @@ -1300,6 +1313,7 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub /* Do the actual replacement and put the result back into subject_str for further replacements. */ if ((result = php_pcre_replace(regex_str, + subject_str, subject_str->val, (int)subject_str->len, replace_value, @@ -1320,6 +1334,7 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub return subject_str; } else { result = php_pcre_replace(Z_STR_P(regex), + subject_str, subject_str->val, (int)subject_str->len, replace, diff --git a/ext/pcre/php_pcre.h b/ext/pcre/php_pcre.h index dc923fe62f..88f810493f 100644 --- a/ext/pcre/php_pcre.h +++ b/ext/pcre/php_pcre.h @@ -33,7 +33,7 @@ #include <locale.h> #endif -PHPAPI zend_string *php_pcre_replace(zend_string *regex, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int limit, int *replace_count); +PHPAPI zend_string *php_pcre_replace(zend_string *regex, zend_string *subject_str, char *subject, int subject_len, zval *replace_val, int is_callable_replace, int limit, int *replace_count); PHPAPI pcre* pcre_get_compiled_regex(zend_string *regex, pcre_extra **extra, int *options); PHPAPI pcre* pcre_get_compiled_regex_ex(zend_string *regex, pcre_extra **extra, int *preg_options, int *coptions); @@ -59,7 +59,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(zend_string *regex); PHPAPI void php_pcre_match_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, zval *subpats, int global, int use_flags, zend_long flags, zend_long start_offset); -PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, +PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *subject_str, char *subject, int subject_len, zval *return_value, int is_callable_replace, int limit, int *replace_count); PHPAPI void php_pcre_split_impl( pcre_cache_entry *pce, char *subject, int subject_len, zval *return_value, |