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

Reply via email to