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