diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 0c1c1ee380de5..2793831d00c36 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -608,6 +608,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 7e0fbe84dcebe..ec5e94aa8200d 100755 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -923,6 +923,16 @@ 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() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_starts_with, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, haystack, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, needle, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_ends_with, 0, 2, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, haystack, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, needle, IS_STRING, 0) +ZEND_END_ARG_INFO() + 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(0, chunklen, IS_LONG, 0) @@ -2496,6 +2506,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); @@ -3128,6 +3140,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 a22992aa81737..e92d981cf72ac 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1866,6 +1866,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; + int k; + + 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; + } + + k = ZSTR_LEN(haystack) - ZSTR_LEN(needle); + RETURN_BOOL(memcmp(&(ZSTR_VAL(haystack))[k], 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 0000000000000..fd478f57cb0e7 --- /dev/null +++ b/ext/standard/tests/strings/str_ends_with.phpt @@ -0,0 +1,45 @@ +--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 0000000000000..a90c12a80f971 --- /dev/null +++ b/ext/standard/tests/strings/str_starts_with.phpt @@ -0,0 +1,45 @@ +--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) +