]> granicus.if.org Git - php/commitdiff
- Unicode impl of substr_count()
authorRolland Santimano <rolland@php.net>
Sat, 27 Aug 2005 19:14:05 +0000 (19:14 +0000)
committerRolland Santimano <rolland@php.net>
Sat, 27 Aug 2005 19:14:05 +0000 (19:14 +0000)
ext/standard/string.c

index b64b07b73841bff5b25d3a1174fbd74e380a4e36..fabaa2d14597e3238d683171549e503e7f6132aa 100644 (file)
@@ -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++;
+                       }
                }
        }