diff options
Diffstat (limited to 'ext/standard/string.c')
-rw-r--r-- | ext/standard/string.c | 258 |
1 files changed, 49 insertions, 209 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c index 068c6e82c4..18ca7e9947 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1813,79 +1813,34 @@ PHPAPI size_t php_strcspn(char *s1, char *s2, char *s1_end, char *s2_end) } /* }}} */ -/* {{{ php_needle_char - */ -static int php_needle_char(zval *needle, char *target) -{ - switch (Z_TYPE_P(needle)) { - case IS_LONG: - *target = (char)Z_LVAL_P(needle); - return SUCCESS; - case IS_NULL: - case IS_FALSE: - *target = '\0'; - return SUCCESS; - case IS_TRUE: - *target = '\1'; - return SUCCESS; - case IS_DOUBLE: - *target = (char)(int)Z_DVAL_P(needle); - return SUCCESS; - case IS_OBJECT: - *target = (char) zval_get_long(needle); - return SUCCESS; - default: - php_error_docref(NULL, E_WARNING, "needle is not a string or an integer"); - return FAILURE; - } -} -/* }}} */ - /* {{{ proto string stristr(string haystack, string needle[, bool part]) Finds first occurrence of a string within another, case insensitive */ PHP_FUNCTION(stristr) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; size_t found_offset; char *haystack_dup; - char needle_char[2]; + char *orig_needle; zend_bool part = 0; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_BOOL(part) ZEND_PARSE_PARAMETERS_END(); - haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack)); - - if (Z_TYPE_P(needle) == IS_STRING) { - char *orig_needle; - if (!Z_STRLEN_P(needle)) { - php_error_docref(NULL, E_WARNING, "Empty needle"); - efree(haystack_dup); - RETURN_FALSE; - } - orig_needle = estrndup(Z_STRVAL_P(needle), Z_STRLEN_P(needle)); - found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), Z_STRLEN_P(needle)); - efree(orig_needle); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - efree(haystack_dup); - RETURN_FALSE; - } - needle_char[1] = 0; - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = php_stristr(haystack_dup, needle_char, ZSTR_LEN(haystack), 1); + if (!ZSTR_LEN(needle)) { + php_error_docref(NULL, E_WARNING, "Empty needle"); + RETURN_FALSE; } + haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack)); + orig_needle = estrndup(ZSTR_VAL(needle), ZSTR_LEN(needle)); + found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), ZSTR_LEN(needle)); + efree(orig_needle); + if (found) { found_offset = found - haystack_dup; if (part) { @@ -1905,40 +1860,25 @@ PHP_FUNCTION(stristr) Finds first occurrence of a string within another */ PHP_FUNCTION(strstr) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; - char needle_char[2]; zend_long found_offset; zend_bool part = 0; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_BOOL(part) ZEND_PARSE_PARAMETERS_END(); - if (Z_TYPE_P(needle) == IS_STRING) { - if (!Z_STRLEN_P(needle)) { - php_error_docref(NULL, E_WARNING, "Empty needle"); - RETURN_FALSE; - } - - found = php_memnstr(ZSTR_VAL(haystack), Z_STRVAL_P(needle), Z_STRLEN_P(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - RETURN_FALSE; - } - needle_char[1] = 0; - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = php_memnstr(ZSTR_VAL(haystack), needle_char, 1, ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); + if (!ZSTR_LEN(needle)) { + php_error_docref(NULL, E_WARNING, "Empty needle"); + RETURN_FALSE; } + found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); + if (found) { found_offset = found - ZSTR_VAL(haystack); if (part) { @@ -1959,15 +1899,13 @@ PHP_FUNCTION(strstr) Finds position of first occurrence of a string within another */ PHP_FUNCTION(strpos) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; - char needle_char[2]; - zend_long offset = 0; + zend_long offset = 0; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END(); @@ -1980,32 +1918,15 @@ PHP_FUNCTION(strpos) RETURN_FALSE; } - if (Z_TYPE_P(needle) == IS_STRING) { - if (!Z_STRLEN_P(needle)) { - php_error_docref(NULL, E_WARNING, "Empty needle"); - RETURN_FALSE; - } - - found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset, - Z_STRVAL_P(needle), - Z_STRLEN_P(needle), - ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - RETURN_FALSE; - } - needle_char[1] = 0; - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset, - needle_char, - 1, - ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); + if (!ZSTR_LEN(needle)) { + php_error_docref(NULL, E_WARNING, "Empty needle"); + RETURN_FALSE; } + found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset, + ZSTR_VAL(needle), ZSTR_LEN(needle), + ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); + if (found) { RETURN_LONG(found - ZSTR_VAL(haystack)); } else { @@ -2019,15 +1940,13 @@ PHP_FUNCTION(strpos) PHP_FUNCTION(stripos) { const char *found = NULL; - zend_string *haystack; + zend_string *haystack, *needle; zend_long offset = 0; - char needle_char[2]; - zval *needle; zend_string *needle_dup = NULL, *haystack_dup; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END(); @@ -2044,33 +1963,14 @@ PHP_FUNCTION(stripos) RETURN_FALSE; } - if (Z_TYPE_P(needle) == IS_STRING) { - if (Z_STRLEN_P(needle) == 0 || Z_STRLEN_P(needle) > ZSTR_LEN(haystack)) { - RETURN_FALSE; - } - - haystack_dup = php_string_tolower(haystack); - needle_dup = php_string_tolower(Z_STR_P(needle)); - found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, - ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack)); - } else { - if (php_needle_char(needle, needle_char) != SUCCESS) { - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - haystack_dup = php_string_tolower(haystack); - needle_char[0] = tolower(needle_char[0]); - needle_char[1] = '\0'; - found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, - needle_char, - sizeof(needle_char) - 1, - ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack)); + if (ZSTR_LEN(needle) == 0 || ZSTR_LEN(needle) > ZSTR_LEN(haystack)) { + RETURN_FALSE; } + haystack_dup = php_string_tolower(haystack); + needle_dup = php_string_tolower(needle); + found = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, + ZSTR_VAL(needle_dup), ZSTR_LEN(needle_dup), ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack)); if (found) { RETVAL_LONG(found - ZSTR_VAL(haystack_dup)); @@ -2089,38 +1989,20 @@ PHP_FUNCTION(stripos) Finds position of last occurrence of a string within another string */ PHP_FUNCTION(strrpos) { - zval *zneedle; zend_string *haystack; + char *needle; size_t needle_len; zend_long offset = 0; - char ord_needle[2]; - const char *p, *e, *found, *needle; + const char *p, *e, *found; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(zneedle) + Z_PARAM_STRING(needle, needle_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - if (Z_TYPE_P(zneedle) == IS_STRING) { - needle = Z_STRVAL_P(zneedle); - needle_len = Z_STRLEN_P(zneedle); - } else { - if (php_needle_char(zneedle, ord_needle) != SUCCESS) { - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - ord_needle[1] = '\0'; - needle = ord_needle; - needle_len = 1; - } - - if ((ZSTR_LEN(haystack) == 0) || (needle_len == 0)) { + if (ZSTR_LEN(haystack) == 0 || needle_len == 0) { RETURN_FALSE; } @@ -2156,49 +2038,29 @@ PHP_FUNCTION(strrpos) Finds position of last occurrence of a string within another string */ PHP_FUNCTION(strripos) { - zval *zneedle; zend_string *needle; zend_string *haystack; zend_long offset = 0; const char *p, *e, *found; - zend_string *needle_dup, *haystack_dup, *ord_needle = NULL; - ALLOCA_FLAG(use_heap); + zend_string *needle_dup, *haystack_dup; ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(zneedle) + Z_PARAM_STR(needle) Z_PARAM_OPTIONAL Z_PARAM_LONG(offset) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - ZSTR_ALLOCA_ALLOC(ord_needle, 1, use_heap); - if (Z_TYPE_P(zneedle) == IS_STRING) { - needle = Z_STR_P(zneedle); - } else { - if (php_needle_char(zneedle, ZSTR_VAL(ord_needle)) != SUCCESS) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - ZSTR_VAL(ord_needle)[1] = '\0'; - needle = ord_needle; - } - - if ((ZSTR_LEN(haystack) == 0) || (ZSTR_LEN(needle) == 0)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); + if (ZSTR_LEN(haystack) == 0 || ZSTR_LEN(needle) == 0) { RETURN_FALSE; } if (ZSTR_LEN(needle) == 1) { /* Single character search can shortcut memcmps Can also avoid tolower emallocs */ + char lowered; if (offset >= 0) { if ((size_t)offset > ZSTR_LEN(haystack)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); RETURN_FALSE; } @@ -2207,22 +2069,19 @@ PHP_FUNCTION(strripos) } else { p = ZSTR_VAL(haystack); if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); RETURN_FALSE; } e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + (size_t)offset; } /* Borrow that ord_needle buffer to avoid repeatedly tolower()ing needle */ - *ZSTR_VAL(ord_needle) = tolower(*ZSTR_VAL(needle)); + lowered = tolower(*ZSTR_VAL(needle)); while (e >= p) { - if (tolower(*e) == *ZSTR_VAL(ord_needle)) { - ZSTR_ALLOCA_FREE(ord_needle, use_heap); + if (tolower(*e) == lowered) { RETURN_LONG(e - p + (offset > 0 ? offset : 0)); } e--; } - ZSTR_ALLOCA_FREE(ord_needle, use_heap); RETURN_FALSE; } @@ -2230,7 +2089,6 @@ PHP_FUNCTION(strripos) if (offset >= 0) { if ((size_t)offset > ZSTR_LEN(haystack)) { zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); RETURN_FALSE; } @@ -2239,7 +2097,6 @@ PHP_FUNCTION(strripos) } else { if (offset < -INT_MAX || (size_t)(-offset) > ZSTR_LEN(haystack)) { zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); php_error_docref(NULL, E_WARNING, "Offset is greater than the length of haystack string"); RETURN_FALSE; } @@ -2256,11 +2113,9 @@ PHP_FUNCTION(strripos) RETVAL_LONG(found - ZSTR_VAL(haystack_dup)); zend_string_release_ex(needle_dup, 0); zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); } else { zend_string_release_ex(needle_dup, 0); zend_string_release_ex(haystack_dup, 0); - ZSTR_ALLOCA_FREE(ord_needle, use_heap); RETURN_FALSE; } } @@ -2270,31 +2125,16 @@ PHP_FUNCTION(strripos) Finds the last occurrence of a character in a string within another */ PHP_FUNCTION(strrchr) { - zval *needle; - zend_string *haystack; + zend_string *haystack, *needle; const char *found = NULL; zend_long found_offset; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STR(haystack) - Z_PARAM_ZVAL(needle) + Z_PARAM_STR(needle) ZEND_PARSE_PARAMETERS_END(); - if (Z_TYPE_P(needle) == IS_STRING) { - found = zend_memrchr(ZSTR_VAL(haystack), *Z_STRVAL_P(needle), ZSTR_LEN(haystack)); - } else { - char needle_chr; - if (php_needle_char(needle, &needle_chr) != SUCCESS) { - RETURN_FALSE; - } - - php_error_docref(NULL, E_DEPRECATED, - "Non-string needles will be interpreted as strings in the future. " \ - "Use an explicit chr() call to preserve the current behavior"); - - found = zend_memrchr(ZSTR_VAL(haystack), needle_chr, ZSTR_LEN(haystack)); - } - + found = zend_memrchr(ZSTR_VAL(haystack), *ZSTR_VAL(needle), ZSTR_LEN(haystack)); if (found) { found_offset = found - ZSTR_VAL(haystack); RETURN_STRINGL(found, ZSTR_LEN(haystack) - found_offset); |