From c7ad26fbf475e4ed5c767a770633319377680a79 Mon Sep 17 00:00:00 2001 From: Rolland Santimano Date: Sat, 27 Aug 2005 19:14:05 +0000 Subject: [PATCH] - Unicode impl of substr_count() --- ext/standard/string.c | 95 ++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 33 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index b64b07b738..fabaa2d145 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -5202,62 +5202,91 @@ PHP_FUNCTION(strnatcasecmp) 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++; + } } } -- 2.50.1