]> granicus.if.org Git - php/commitdiff
Rewrite strrpos and strripos to be binary safe and behave the way their prototype...
authorSara Golemon <pollita@php.net>
Sat, 12 Apr 2003 07:36:22 +0000 (07:36 +0000)
committerSara Golemon <pollita@php.net>
Sat, 12 Apr 2003 07:36:22 +0000 (07:36 +0000)
ext/standard/string.c

index a7ab405ee81e7ce253c86d4ee889e45047bb16f3..aba93f505928439d78d5fc7a6907d22aef7efcb0 100644 (file)
@@ -1568,87 +1568,82 @@ PHP_FUNCTION(stripos)
 /* }}} */
 
 /* {{{ proto int strrpos(string haystack, string needle [, int offset])
-   Finds position of last occurrence of a character in a string within another */
+   Finds position of last occurrence of a string within another string */
 PHP_FUNCTION(strrpos)
 {
-       zval **haystack, **needle, **offset;
-       char *found = NULL;
-       int argc = ZEND_NUM_ARGS();
-       int off = 0;
-       
-       if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &haystack, &needle, &offset) == FAILURE) {
-               WRONG_PARAM_COUNT;
-       }
-       convert_to_string_ex(haystack);
+       char *needle, *haystack;
+       int needle_len, haystack_len, offset = 0;
+       char *p, *e;
 
-       if (argc == 3) {
-               convert_to_long_ex(offset);
-               if (Z_LVAL_PP(offset) < 0 || Z_LVAL_PP(offset) > Z_STRLEN_PP(haystack)) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string.");
-                       RETURN_FALSE;
-               }
-               off = Z_LVAL_PP(offset); 
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &haystack, &haystack_len, &needle, &needle_len, &offset) == FAILURE) {
+               RETURN_FALSE;
        }
 
-       if (Z_TYPE_PP(needle) == IS_STRING) {
-               found = strrchr(Z_STRVAL_PP(haystack) + off, *Z_STRVAL_PP(needle));
+       if (offset >= 0) {
+               p = haystack + offset;
+               e = haystack + haystack_len - needle_len;
        } else {
-               convert_to_long_ex(needle);
-               found = strrchr(Z_STRVAL_PP(haystack) + off, (char) Z_LVAL_PP(needle));
+               p = haystack;
+               if (needle_len > -offset) {
+                       e = haystack + haystack_len - needle_len;
+               } else {
+                       e = haystack + haystack_len + offset;
+               }
        }
 
-       if (found) {
-               RETURN_LONG(Z_STRLEN_PP(haystack) - strlen(found));
-       } else {
-               RETURN_FALSE;
+       while (e >= p) {
+               if (memcmp(e, needle, needle_len) == 0) {
+                       RETURN_LONG(e - p);
+               }
+               e--;
        }
+
+       RETURN_FALSE;
 }
 /* }}} */
 
 /* {{{ proto int strripos(string haystack, string needle [, int offset])
-   Finds position of last occurrence of a character in a string within another, case insensitive */
+   Finds position of last occurrence of a string within another string */
 PHP_FUNCTION(strripos)
 {
-       zval **haystack, **needle, **offset;
-       char *found = NULL;
-       int argc = ZEND_NUM_ARGS();
-       int off = 0;
-       char *haystack_dup;
-       char needle_dup;
-       
-       if (argc < 2 || argc > 3 || zend_get_parameters_ex(argc, &haystack, &needle, &offset) == FAILURE) {
-               WRONG_PARAM_COUNT;
-       }
-       convert_to_string_ex(haystack);
+       char *needle, *haystack;
+       int needle_len, haystack_len, offset = 0;
+       char *p, *e;
+       char *needle_dup, *haystack_dup;
 
-       if (argc == 3) {
-               convert_to_long_ex(offset);
-               if (Z_LVAL_PP(offset) < 0 || Z_LVAL_PP(offset) > Z_STRLEN_PP(haystack)) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset not contained in string.");
-                       RETURN_FALSE;
-               }
-               off = Z_LVAL_PP(offset); 
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &haystack, &haystack_len, &needle, &needle_len, &offset) == FAILURE) {
+               RETURN_FALSE;
        }
 
-       haystack_dup = estrndup(Z_STRVAL_PP(haystack), Z_STRLEN_PP(haystack));
-       php_strtolower(haystack_dup, Z_STRLEN_PP(haystack));
+       needle_dup = estrndup(needle, needle_len);
+       php_strtolower(needle_dup, needle_len);
+       haystack_dup = estrndup(haystack, haystack_len);
+       php_strtolower(haystack_dup, haystack_len);
 
-       if (Z_TYPE_PP(needle) == IS_STRING) {
-               needle_dup = *Z_STRVAL_PP(needle);
+       if (offset >= 0) {
+               p = haystack_dup + offset;
+               e = haystack_dup + haystack_len - needle_len;
        } else {
-               convert_to_long_ex(needle);
-               needle_dup = (char) Z_LVAL_PP(needle);
+               p = haystack_dup;
+               if (needle_len > -offset) {
+                       e = haystack_dup + haystack_len - needle_len;
+               } else {
+                       e = haystack_dup + haystack_len + offset;
+               }
        }
 
-       found = strrchr(haystack_dup + off, tolower(needle_dup));
+       while (e >= p) {
+               if (memcmp(e, needle_dup, needle_len) == 0) {
+                       efree(haystack_dup);
+                       efree(needle_dup);
+                       RETURN_LONG(e - p);
+               }
+               e--;
+       }
 
        efree(haystack_dup);
-
-       if (found) {
-               RETURN_LONG(Z_STRLEN_PP(haystack) - strlen(found));
-       } else {
-               RETURN_FALSE;
-       }
+       efree(needle_dup);
+       RETURN_FALSE;
 }
 /* }}} */