From: William Hudgins Date: Tue, 5 May 2020 13:57:39 +0000 (+0200) Subject: Add str_starts_with() and str_ends_with() X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=31fb6a08b3a02e665d0e24d2cbd56d13342423c8;p=php Add str_starts_with() and str_ends_with() RFC: https://wiki.php.net/rfc/add_str_starts_with_and_ends_with_functions Closes GH-5300. --- diff --git a/UPGRADING b/UPGRADING index 668b3dd59b..233f78fdae 100644 --- a/UPGRADING +++ b/UPGRADING @@ -568,9 +568,16 @@ PHP 8.0 UPGRADE NOTES PR: https://github.com/php/php-src/pull/4797 - Standard: - . Added str_contains($haystack, $needle) function, which checks whether - $haystack contains $needle as a sub-string. It is equivalent to writing - strpos($haystack, $needle) !== false. + . Added + + str_contains(string $haystack, string $needle): bool + str_starts_with(string $haystack, string $needle): bool + str_ends_with(string $haystack, string $needle): bool + + functions, which check whether $haystack contains, starts with or ends with + $needle. + RFC: https://wiki.php.net/rfc/str_contains + RFC: https://wiki.php.net/rfc/add_str_starts_with_and_ends_with_functions . Added fdiv() function, which performs a floating-point division under IEEE 754 semantics. Division by zero is considered well-defined and will return one of Inf, -Inf or NaN. diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index e750d2229c..2017549e9b 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -604,6 +604,10 @@ function strrchr(string $haystack, string $needle): string|false {} function str_contains(string $haystack, string $needle): bool {} +function str_starts_with(string $haystack, string $needle): bool {} + +function str_ends_with(string $haystack, string $needle): bool {} + function chunk_split(string $str, int $chunklen = 76, string $ending = "\r\n"): string {} function substr(string $str, int $start, ?int $length = null): string|false {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index f7c9805683..5e2e457ea2 100755 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -923,6 +923,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_contains, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, needle, IS_STRING, 0) ZEND_END_ARG_INFO() +#define arginfo_str_starts_with arginfo_str_contains + +#define arginfo_str_ends_with arginfo_str_contains + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_chunk_split, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, chunklen, IS_LONG, 0, "76") @@ -2496,6 +2500,8 @@ ZEND_FUNCTION(strrpos); ZEND_FUNCTION(strripos); ZEND_FUNCTION(strrchr); ZEND_FUNCTION(str_contains); +ZEND_FUNCTION(str_starts_with); +ZEND_FUNCTION(str_ends_with); ZEND_FUNCTION(chunk_split); ZEND_FUNCTION(substr); ZEND_FUNCTION(substr_replace); @@ -3129,6 +3135,8 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(strripos, arginfo_strripos) ZEND_FE(strrchr, arginfo_strrchr) ZEND_FE(str_contains, arginfo_str_contains) + ZEND_FE(str_starts_with, arginfo_str_starts_with) + ZEND_FE(str_ends_with, arginfo_str_ends_with) ZEND_FE(chunk_split, arginfo_chunk_split) ZEND_FE(substr, arginfo_substr) ZEND_FE(substr_replace, arginfo_substr_replace) diff --git a/ext/standard/string.c b/ext/standard/string.c index c2e9fe3c27..5b0df571d6 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1864,6 +1864,44 @@ PHP_FUNCTION(str_contains) } /* }}} */ +/* {{{ proto bool str_starts_with(string haystack, string needle) + Checks if haystack starts with needle */ +PHP_FUNCTION(str_starts_with) +{ + zend_string *haystack, *needle; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(haystack) + Z_PARAM_STR(needle) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(needle) > ZSTR_LEN(haystack)) { + RETURN_FALSE; + } + + RETURN_BOOL(memcmp(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle)) == 0); +} + +/* {{{ proto bool str_ends_with(string haystack, string needle) + Checks if haystack ends with needle */ +PHP_FUNCTION(str_ends_with) +{ + zend_string *haystack, *needle; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(haystack) + Z_PARAM_STR(needle) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(needle) > ZSTR_LEN(haystack)) { + RETURN_FALSE; + } + + RETURN_BOOL(memcmp( + ZSTR_VAL(haystack) + ZSTR_LEN(haystack) - ZSTR_LEN(needle), + ZSTR_VAL(needle), ZSTR_LEN(needle)) == 0); +} + /* {{{ proto string strchr(string haystack, string needle) An alias for strstr */ /* }}} */ diff --git a/ext/standard/tests/strings/str_ends_with.phpt b/ext/standard/tests/strings/str_ends_with.phpt new file mode 100644 index 0000000000..8aa5f0aa1c --- /dev/null +++ b/ext/standard/tests/strings/str_ends_with.phpt @@ -0,0 +1,44 @@ +--TEST-- +str_ends_with() function - unit tests for str_ends_with() +--FILE-- + +--EXPECT-- +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) diff --git a/ext/standard/tests/strings/str_starts_with.phpt b/ext/standard/tests/strings/str_starts_with.phpt new file mode 100644 index 0000000000..776d945dae --- /dev/null +++ b/ext/standard/tests/strings/str_starts_with.phpt @@ -0,0 +1,44 @@ +--TEST-- +str_starts_with() function - unit tests for str_starts_with() +--FILE-- + +--EXPECT-- +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +bool(true) +bool(false) +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false)