summaryrefslogtreecommitdiff
path: root/ext/standard/string.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/standard/string.c')
-rw-r--r--ext/standard/string.c299
1 files changed, 59 insertions, 240 deletions
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 706828c6a9..d0797725bd 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -1798,79 +1798,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) {
@@ -1890,40 +1845,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) {
@@ -1944,15 +1884,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();
@@ -1965,32 +1903,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 {
@@ -2004,15 +1925,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();
@@ -2029,33 +1948,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));
@@ -2074,38 +1974,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;
}
@@ -2141,49 +2023,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;
}
@@ -2192,22 +2054,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;
}
@@ -2215,7 +2074,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;
}
@@ -2224,7 +2082,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;
}
@@ -2241,11 +2098,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;
}
}
@@ -2255,31 +2110,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);
@@ -2737,8 +2577,8 @@ PHP_FUNCTION(quotemeta)
old_end = ZSTR_VAL(old) + ZSTR_LEN(old);
- if (ZSTR_VAL(old) == old_end) {
- RETURN_FALSE;
+ if (ZSTR_LEN(old) == 0) {
+ RETURN_EMPTY_STRING();
}
str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0);
@@ -4898,7 +4738,7 @@ PHP_FUNCTION(setlocale)
}
/* }}} */
-/* {{{ proto void parse_str(string encoded_string [, array &result])
+/* {{{ proto void parse_str(string encoded_string, array &result)
Parses GET/POST/COOKIE data and sets global variables */
PHP_FUNCTION(parse_str)
{
@@ -4907,39 +4747,18 @@ PHP_FUNCTION(parse_str)
char *res = NULL;
size_t arglen;
- ZEND_PARSE_PARAMETERS_START(1, 2)
+ ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_STRING(arg, arglen)
- Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(arrayArg)
ZEND_PARSE_PARAMETERS_END();
- res = estrndup(arg, arglen);
-
- if (arrayArg == NULL) {
- zval tmp;
- zend_array *symbol_table;
- if (zend_forbid_dynamic_call("parse_str() with a single argument") == FAILURE) {
- efree(res);
- return;
- }
-
- php_error_docref(NULL, E_DEPRECATED, "Calling parse_str() without the result argument is deprecated");
-
- symbol_table = zend_rebuild_symbol_table();
- ZVAL_ARR(&tmp, symbol_table);
- sapi_module.treat_data(PARSE_STRING, res, &tmp);
- if (UNEXPECTED(zend_hash_del(symbol_table, ZSTR_KNOWN(ZEND_STR_THIS)) == SUCCESS)) {
- zend_throw_error(NULL, "Cannot re-assign $this");
- }
- } else {
- arrayArg = zend_try_array_init(arrayArg);
- if (!arrayArg) {
- efree(res);
- return;
- }
-
- sapi_module.treat_data(PARSE_STRING, res, arrayArg);
+ arrayArg = zend_try_array_init(arrayArg);
+ if (!arrayArg) {
+ return;
}
+
+ res = estrndup(arg, arglen);
+ sapi_module.treat_data(PARSE_STRING, res, arrayArg);
}
/* }}} */