Browse Source

- Unicode impl of substr_count()

migration/RELEASE_1_0_0
Rolland Santimano 21 years ago
parent
commit
c7ad26fbf4
  1. 95
      ext/standard/string.c

95
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++;
}
}
}

Loading…
Cancel
Save