rolland Sat Aug 27 15:14:05 2005 EDT Modified files: /php-src/ext/standard string.c Log: - Unicode impl of substr_count() http://cvs.php.net/diff.php/php-src/ext/standard/string.c?r1=1.473&r2=1.474&ty=u Index: php-src/ext/standard/string.c diff -u php-src/ext/standard/string.c:1.473 php-src/ext/standard/string.c:1.474 --- php-src/ext/standard/string.c:1.473 Fri Aug 26 06:21:07 2005 +++ php-src/ext/standard/string.c Sat Aug 27 15:14:05 2005 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: string.c,v 1.473 2005/08/26 10:21:07 rolland Exp $ */ +/* $Id: string.c,v 1.474 2005/08/27 19:14:05 rolland Exp $ */ /* Synced with php 3.0 revision 1.193 1999-06-16 [ssb] */ @@ -5202,62 +5202,91 @@ Returns the number of times a substring occurs in the string */ PHP_FUNCTION(substr_count) { - zval **haystack, **needle, **offset, **length; + void *haystack, *needle; + int32_t haystack_len, needle_len; + zend_uchar haystack_type, needle_type; + long offset = 0, length = 0; int ac = ZEND_NUM_ARGS(); int count = 0; - char *p, *endp, cmp; - - if (ac < 2 || ac > 4 || zend_get_parameters_ex(ac, &haystack, &needle, &offset, &length) == FAILURE) { - WRONG_PARAM_COUNT; + void *p, *endp, *tmp; + int32_t i, j; + char cmp; + + if (zend_parse_parameters(ac TSRMLS_CC, "TT|ll", + &haystack, &haystack_len, &haystack_type, + &needle, &needle_len, &needle_type, + &offset, &length) == FAILURE) { + return; } - convert_to_string_ex(haystack); - convert_to_string_ex(needle); - - if (Z_STRLEN_PP(needle) == 0) { + if (needle_len == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring."); RETURN_FALSE; } - - p = Z_STRVAL_PP(haystack); - endp = p + Z_STRLEN_PP(haystack); - + + if (haystack_type == IS_UNICODE) { + p = (UChar *)haystack; + endp = (UChar *)haystack + haystack_len; + } else { + p = (char *)haystack; + endp = (char *)haystack + haystack_len; + } + if (ac > 2) { - convert_to_long_ex(offset); - if (Z_LVAL_PP(offset) < 0) { + if (offset < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset should be greater then or equal to 0."); - RETURN_FALSE; + RETURN_FALSE; + } + if (haystack_type == IS_UNICODE) { + i = 0; + U16_FWD_N((UChar *)haystack, i, haystack_len, offset); + p = (UChar *)haystack + i; + } else { + p = (char *)haystack + offset; } - p += Z_LVAL_PP(offset); if (p > endp) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset value %ld exceeds string length.", Z_LVAL_PP(offset)); - RETURN_FALSE; + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset value %ld exceeds string length.", offset); + RETURN_FALSE; } if (ac == 4) { - convert_to_long_ex(length); - if (Z_LVAL_PP(length) <= 0) { + if (length < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length should be greater than 0."); - RETURN_FALSE; + RETURN_FALSE; } - if ((p + Z_LVAL_PP(length)) > endp) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length value %ld exceeds string length.", Z_LVAL_PP(length)); + if (haystack_type == IS_UNICODE) { + j = i; + i = 0; + U16_FWD_N((UChar *)p, i, haystack_len-j, length); + tmp = (UChar *)p + i; + } else { + tmp = (char *)p + length; + } + if (tmp > endp) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset value %ld exceeds string length.", offset); RETURN_FALSE; + } else { + endp = tmp; } - endp = p + Z_LVAL_PP(length); } } - - if (Z_STRLEN_PP(needle) == 1) { - cmp = Z_STRVAL_PP(needle)[0]; - while ((p = memchr(p, cmp, endp - p))) { + if (haystack_type == IS_UNICODE) { + while ((p = zend_u_memnstr((UChar *)p, (UChar *)needle, needle_len, (UChar *)endp)) != NULL) { + (UChar *)p += needle_len; count++; - p++; } } else { - while ((p = php_memnstr(p, Z_STRVAL_PP(needle), Z_STRLEN_PP(needle), endp))) { - p += Z_STRLEN_PP(needle); - count++; + if (needle_len == 1) { + cmp = ((char *)needle)[0]; + while ((p = memchr(p, cmp, endp - p))) { + count++; + (char *)p++; + } + } else { + while ((p = php_memnstr((char *)p, (char *)needle, needle_len, (char *)endp))) { + (char *)p += needle_len; + count++; + } } }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php