Small correction to the original patch, fixes a segv in sybase-style addslashes code as well as removes unused variable.
Ilia On October 3, 2002 10:21 pm, Ilia A. wrote: > After doing a number of tests on PHP's various string functions, I've came > up with a patch that significantly improves the performance on those > functions. The patch optimizes: > php_addslashes() - internal PHP function used to add slashes to a string > (15-20% speed increase) > php_memnstr() - internal PHP function used to find a multibyte string > inside another string. 35-40% speed increase when string is found, 90-100% > speed increase when the string is not found. > substr_count() - PHP function used to determine the number of times a > string occurs within another string. 20-25% speed increase + additional > speed gains from usage of optimized php_memnstr() function. > > Please let me know if there are any objections, better suggestions, bug > reports (pertaining to this patch) that would need to be resolved before > this bug goes into the CVS. > > Ilia
Index: string.c =================================================================== RCS file: /repository/php4/ext/standard/string.c,v retrieving revision 1.308 diff -u -3 -p -r1.308 string.c --- string.c 3 Oct 2002 18:15:18 -0000 1.308 +++ string.c 4 Oct 2002 02:57:47 -0000 @@ -2416,17 +2416,19 @@ PHPAPI char *php_addslashes(char *str, i char *new_str; char *source, *target; char *end; - char c; if (!str) { *new_length = 0; return str; } new_str = (char *) emalloc((length?length:(length=strlen(str)))*2+1); + source = str; + end = source + length; + target = new_str; + if (PG(magic_quotes_sybase)) { - for (source = str, end = source+length, target = new_str; source < end; source++) { - c = *source; - switch (c) { + while (source<end) { + switch (*source) { case '\0': *target++ = '\\'; *target++ = '0'; @@ -2436,14 +2438,16 @@ PHPAPI char *php_addslashes(char *str, i *target++ = '\''; break; default: - *target++ = c; - break; + *target++ = *source; + break; } + source++; } - } else { - for (source = str, end = source+length, target = new_str; source < end; source++) { - c = *source; - switch (c) { + } + else { + while (source<end) { + switch (*source) + { case '\0': *target++ = '\\'; *target++ = '0'; @@ -2454,11 +2458,14 @@ PHPAPI char *php_addslashes(char *str, i *target++ = '\\'; /* break is missing *intentionally* */ default: - *target++ = c; - break; + *target++ = *source; + break; } + + source++; } } + *target = 0; if (new_length) { *new_length = target - new_str; @@ -3794,7 +3801,7 @@ PHP_FUNCTION(strnatcasecmp) PHP_FUNCTION(substr_count) { zval **haystack, **needle; - int i, length, count = 0; + int count = 0; char *p, *endp, cmp; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &haystack, &needle) == FAILURE) { @@ -3807,25 +3814,23 @@ PHP_FUNCTION(substr_count) if (Z_STRLEN_PP(needle) == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring."); RETURN_FALSE; - } else if (Z_STRLEN_PP(needle) == 1) { - /* Special optimized case to avoid calls to php_memnstr(). */ - for (i = 0, p = Z_STRVAL_PP(haystack), - length = Z_STRLEN_PP(haystack), cmp = Z_STRVAL_PP(needle)[0]; - i < length; i++) { - if (p[i] == cmp) { - count++; + } + + p = Z_STRVAL_PP(haystack); + endp = p + Z_STRLEN_PP(haystack); + + if (Z_STRLEN_PP(needle) == 1) { + cmp = Z_STRVAL_PP(needle)[0]; + + while (p < endp) { + if (*(p++) == cmp) { + count++; } } } else { - p = Z_STRVAL_PP(haystack); - endp = p + Z_STRLEN_PP(haystack); - while (p <= endp) { - if ( (p = php_memnstr(p, Z_STRVAL_PP(needle), Z_STRLEN_PP(needle), endp)) != NULL ) { - p += Z_STRLEN_PP(needle); - count++; - } else { - break; - } + while ((p = php_memnstr(p, Z_STRVAL_PP(needle), Z_STRLEN_PP(needle), endp))) { + p += Z_STRLEN_PP(needle); + count++; } } Index: php_string.h =================================================================== RCS file: /repository/php4/ext/standard/php_string.h,v retrieving revision 1.61 diff -u -3 -p -r1.61 php_string.h --- php_string.h 25 Sep 2002 18:06:05 -0000 1.61 +++ php_string.h 4 Oct 2002 02:57:47 -0000 @@ -133,19 +133,24 @@ static inline char * php_memnstr(char *haystack, char *needle, int needle_len, char *end) { char *p = haystack; - char first = *needle; + char ne = needle[needle_len-1]; - /* let end point to the last character where needle may start */ end -= needle_len; - + while (p <= end) { - while (*p != first) - if (++p > end) - return NULL; - if (memcmp(p, needle, needle_len) == 0) - return p; + if ((p = memchr(p, *needle, (end-p))) && ne == p[needle_len-1]) { + if (!memcmp(needle, p, needle_len-1)) { + return p; + } + } + + if (p == NULL) { + return NULL; + } + p++; } + return NULL; }
-- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php