From 57f795abd26d6583d8f9de986ee2d57e151d7aa0 Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Fri, 16 Jan 2026 17:28:49 +0100 Subject: [PATCH 1/2] Add functions that work with suffixes and prefixes # Conflicts: # ext/standard/basic_functions_arginfo.h --- Zend/Optimizer/zend_func_infos.h | 6 + ext/standard/basic_functions.stub.php | 36 ++++ ext/standard/basic_functions_arginfo.h | 40 ++++- ext/standard/string.c | 160 ++++++++++++++++++ .../tests/strings/str_prefix_ensure.phpt | 64 +++++++ .../tests/strings/str_prefix_remove.phpt | 64 +++++++ .../tests/strings/str_prefix_replace.phpt | 66 ++++++++ .../tests/strings/str_suffix_ensure.phpt | 64 +++++++ .../tests/strings/str_suffix_remove.phpt | 64 +++++++ .../tests/strings/str_suffix_replace.phpt | 66 ++++++++ 10 files changed, 629 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/strings/str_prefix_ensure.phpt create mode 100644 ext/standard/tests/strings/str_prefix_remove.phpt create mode 100644 ext/standard/tests/strings/str_prefix_replace.phpt create mode 100644 ext/standard/tests/strings/str_suffix_ensure.phpt create mode 100644 ext/standard/tests/strings/str_suffix_remove.phpt create mode 100644 ext/standard/tests/strings/str_suffix_replace.phpt diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index b7b118c710c53..89d435a1a6328 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -481,6 +481,12 @@ static const func_info_t func_infos[] = { F1("stristr", MAY_BE_STRING|MAY_BE_FALSE), F1("strstr", MAY_BE_STRING|MAY_BE_FALSE), F1("strrchr", MAY_BE_STRING|MAY_BE_FALSE), + F1("str_prefix_ensure", MAY_BE_STRING), + F1("str_prefix_remove", MAY_BE_STRING), + F1("str_prefix_replace", MAY_BE_STRING), + F1("str_suffix_ensure", MAY_BE_STRING), + F1("str_suffix_remove", MAY_BE_STRING), + F1("str_suffix_replace", MAY_BE_STRING), F1("chunk_split", MAY_BE_STRING), FN("substr_replace", MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING), F1("quotemeta", MAY_BE_STRING), diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index e27dca069c55b..dbe4f78ad6798 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2429,6 +2429,42 @@ function str_starts_with(string $haystack, string $needle): bool {} /** @compile-time-eval */ function str_ends_with(string $haystack, string $needle): bool {} +/** + * @compile-time-eval + * @refcount 1 + */ +function str_prefix_ensure(string $prefix, string $subject): string {} + +/** + * @compile-time-eval + * @refcount 1 + */ +function str_prefix_remove(string $prefix, string $subject): string {} + +/** + * @compile-time-eval + * @refcount 1 + */ +function str_prefix_replace(string $prefix, string $replace, string $subject): string {} + +/** + * @compile-time-eval + * @refcount 1 + */ +function str_suffix_ensure(string $suffix, string $subject): string {} + +/** + * @compile-time-eval + * @refcount 1 + */ +function str_suffix_remove(string $suffix, string $subject): string {} + +/** + * @compile-time-eval + * @refcount 1 + */ +function str_suffix_replace(string $suffix, string $replace, string $subject): string {} + /** * @compile-time-eval * @refcount 1 diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 9f5d89991da9b..d49d442b1ec53 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit basic_functions.stub.php instead. - * Stub hash: 1a1667a5c59111f096a758d5bb4aa7cf3ec09cfe */ + * Stub hash: ed8b640a6ea3d5fcb1a3c571bfe98c794e6448b4 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -928,6 +928,32 @@ ZEND_END_ARG_INFO() #define arginfo_str_ends_with arginfo_str_contains +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_prefix_ensure, 0, 2, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_str_prefix_remove arginfo_str_prefix_ensure + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_prefix_replace, 0, 3, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, replace, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_suffix_ensure, 0, 2, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, suffix, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) +ZEND_END_ARG_INFO() + +#define arginfo_str_suffix_remove arginfo_str_suffix_ensure + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_suffix_replace, 0, 3, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, suffix, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, replace, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, subject, 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, string, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, length, IS_LONG, 0, "76") @@ -2560,6 +2586,12 @@ ZEND_FUNCTION(strrchr); ZEND_FUNCTION(str_contains); ZEND_FUNCTION(str_starts_with); ZEND_FUNCTION(str_ends_with); +ZEND_FUNCTION(str_prefix_ensure); +ZEND_FUNCTION(str_prefix_remove); +ZEND_FUNCTION(str_prefix_replace); +ZEND_FUNCTION(str_suffix_ensure); +ZEND_FUNCTION(str_suffix_remove); +ZEND_FUNCTION(str_suffix_replace); ZEND_FUNCTION(chunk_split); ZEND_FUNCTION(substr); ZEND_FUNCTION(substr_replace); @@ -3162,6 +3194,12 @@ static const zend_function_entry ext_functions[] = { ZEND_RAW_FENTRY("str_contains", zif_str_contains, arginfo_str_contains, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_str_contains, NULL) ZEND_RAW_FENTRY("str_starts_with", zif_str_starts_with, arginfo_str_starts_with, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_str_starts_with, NULL) ZEND_RAW_FENTRY("str_ends_with", zif_str_ends_with, arginfo_str_ends_with, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("str_prefix_ensure", zif_str_prefix_ensure, arginfo_str_prefix_ensure, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("str_prefix_remove", zif_str_prefix_remove, arginfo_str_prefix_remove, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("str_prefix_replace", zif_str_prefix_replace, arginfo_str_prefix_replace, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("str_suffix_ensure", zif_str_suffix_ensure, arginfo_str_suffix_ensure, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("str_suffix_remove", zif_str_suffix_remove, arginfo_str_suffix_remove, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) + ZEND_RAW_FENTRY("str_suffix_replace", zif_str_suffix_replace, arginfo_str_suffix_replace, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("chunk_split", zif_chunk_split, arginfo_chunk_split, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) ZEND_RAW_FENTRY("substr", zif_substr, arginfo_substr, ZEND_ACC_COMPILE_TIME_EVAL, frameless_function_infos_substr, NULL) ZEND_RAW_FENTRY("substr_replace", zif_substr_replace, arginfo_substr_replace, ZEND_ACC_COMPILE_TIME_EVAL, NULL, NULL) diff --git a/ext/standard/string.c b/ext/standard/string.c index 0b7d5be1a2576..d9c79bdfe22b5 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1889,6 +1889,166 @@ PHP_FUNCTION(str_ends_with) } /* }}} */ +/* {{{ Adds prefix to subject string if subject does not already start with prefix */ +PHP_FUNCTION(str_prefix_ensure) +{ + zend_string *subject, *prefix; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(prefix) + Z_PARAM_STR(subject) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(prefix) == 0) { + RETURN_STR_COPY(subject); + } + + if (ZSTR_LEN(prefix) <= ZSTR_LEN(subject) && + memcmp(ZSTR_VAL(subject), ZSTR_VAL(prefix), ZSTR_LEN(prefix)) == 0) { + RETURN_STR_COPY(subject); + } + + zend_string *result = zend_string_alloc(ZSTR_LEN(prefix) + ZSTR_LEN(subject), 0); + memcpy(ZSTR_VAL(result), ZSTR_VAL(prefix), ZSTR_LEN(prefix)); + memcpy(ZSTR_VAL(result) + ZSTR_LEN(prefix), ZSTR_VAL(subject), ZSTR_LEN(subject)); + ZSTR_VAL(result)[ZSTR_LEN(prefix) + ZSTR_LEN(subject)] = '\0'; + RETURN_NEW_STR(result); +} +/* }}} */ + +/* {{{ Removes prefix from subject string if subject starts with prefix */ +PHP_FUNCTION(str_prefix_remove) +{ + zend_string *subject, *prefix; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(prefix) + Z_PARAM_STR(subject) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(prefix) > ZSTR_LEN(subject)) { + RETURN_STR_COPY(subject); + } + + if (memcmp(ZSTR_VAL(subject), ZSTR_VAL(prefix), ZSTR_LEN(prefix)) == 0) { + RETURN_STRINGL(ZSTR_VAL(subject) + ZSTR_LEN(prefix), ZSTR_LEN(subject) - ZSTR_LEN(prefix)); + } + + RETURN_STR_COPY(subject); +} +/* }}} */ + +/* {{{ Replaces prefix in subject string if subject starts with prefix */ +PHP_FUNCTION(str_prefix_replace) +{ + zend_string *subject, *prefix, *replace; + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(prefix) + Z_PARAM_STR(replace) + Z_PARAM_STR(subject) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(prefix) > ZSTR_LEN(subject)) { + RETURN_STR_COPY(subject); + } + + if (memcmp(ZSTR_VAL(subject), ZSTR_VAL(prefix), ZSTR_LEN(prefix)) == 0) { + size_t remaining_len = ZSTR_LEN(subject) - ZSTR_LEN(prefix); + zend_string *result = zend_string_alloc(ZSTR_LEN(replace) + remaining_len, 0); + memcpy(ZSTR_VAL(result), ZSTR_VAL(replace), ZSTR_LEN(replace)); + memcpy(ZSTR_VAL(result) + ZSTR_LEN(replace), ZSTR_VAL(subject) + ZSTR_LEN(prefix), remaining_len); + ZSTR_VAL(result)[ZSTR_LEN(replace) + remaining_len] = '\0'; + RETURN_NEW_STR(result); + } + + RETURN_STR_COPY(subject); +} +/* }}} */ + +/* {{{ Adds suffix to subject string if subject does not already end with suffix */ +PHP_FUNCTION(str_suffix_ensure) +{ + zend_string *subject, *suffix; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(suffix) + Z_PARAM_STR(subject) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(suffix) == 0) { + RETURN_STR_COPY(subject); + } + + if (ZSTR_LEN(suffix) <= ZSTR_LEN(subject) && + memcmp( + ZSTR_VAL(subject) + ZSTR_LEN(subject) - ZSTR_LEN(suffix), + ZSTR_VAL(suffix), ZSTR_LEN(suffix)) == 0) { + RETURN_STR_COPY(subject); + } + + zend_string *result = zend_string_alloc(ZSTR_LEN(subject) + ZSTR_LEN(suffix), 0); + memcpy(ZSTR_VAL(result), ZSTR_VAL(subject), ZSTR_LEN(subject)); + memcpy(ZSTR_VAL(result) + ZSTR_LEN(subject), ZSTR_VAL(suffix), ZSTR_LEN(suffix)); + ZSTR_VAL(result)[ZSTR_LEN(subject) + ZSTR_LEN(suffix)] = '\0'; + RETURN_NEW_STR(result); +} +/* }}} */ + +/* {{{ Removes suffix from subject string if subject ends with suffix */ +PHP_FUNCTION(str_suffix_remove) +{ + zend_string *subject, *suffix; + + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(suffix) + Z_PARAM_STR(subject) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(suffix) > ZSTR_LEN(subject)) { + RETURN_STR_COPY(subject); + } + + if (memcmp( + ZSTR_VAL(subject) + ZSTR_LEN(subject) - ZSTR_LEN(suffix), + ZSTR_VAL(suffix), ZSTR_LEN(suffix)) == 0) { + RETURN_STRINGL(ZSTR_VAL(subject), ZSTR_LEN(subject) - ZSTR_LEN(suffix)); + } + + RETURN_STR_COPY(subject); +} +/* }}} */ + +/* {{{ Replaces suffix in subject string if subject ends with suffix */ +PHP_FUNCTION(str_suffix_replace) +{ + zend_string *subject, *suffix, *replace; + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(suffix) + Z_PARAM_STR(replace) + Z_PARAM_STR(subject) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(suffix) > ZSTR_LEN(subject)) { + RETURN_STR_COPY(subject); + } + + if (memcmp( + ZSTR_VAL(subject) + ZSTR_LEN(subject) - ZSTR_LEN(suffix), + ZSTR_VAL(suffix), ZSTR_LEN(suffix)) == 0) { + size_t base_len = ZSTR_LEN(subject) - ZSTR_LEN(suffix); + zend_string *result = zend_string_alloc(base_len + ZSTR_LEN(replace), 0); + memcpy(ZSTR_VAL(result), ZSTR_VAL(subject), base_len); + memcpy(ZSTR_VAL(result) + base_len, ZSTR_VAL(replace), ZSTR_LEN(replace)); + ZSTR_VAL(result)[base_len + ZSTR_LEN(replace)] = '\0'; + RETURN_NEW_STR(result); + } + + RETURN_STR_COPY(subject); +} +/* }}} */ + static inline void _zend_strpos(zval *return_value, zend_string *haystack, zend_string *needle, zend_long offset) { const char *found = NULL; diff --git a/ext/standard/tests/strings/str_prefix_ensure.phpt b/ext/standard/tests/strings/str_prefix_ensure.phpt new file mode 100644 index 0000000000000..5492ff7176dcc --- /dev/null +++ b/ext/standard/tests/strings/str_prefix_ensure.phpt @@ -0,0 +1,64 @@ +--TEST-- +Test str_prefix_ensure() function +--FILE-- + +--EXPECTF-- +*** Testing str_prefix_ensure() : various strings *** +string(21) "TheBeginningMiddleEnd" +string(18) "BeginningMiddleEnd" +string(18) "BeginningMiddleEnd" +string(6) "prefix" +string(0) "" +string(1) " " +string(4) "abca" +string(4) "test" +string(19) "%0BeginningMiddleEnd" +string(1) "%0" +string(1) "%0" +string(2) "%0a" +string(2) "%0a" +string(7) "%0abc%0ab" +string(5) "c%0%0ab" +string(6) "a%0da%0b" +string(6) "a%0za%0b" diff --git a/ext/standard/tests/strings/str_prefix_remove.phpt b/ext/standard/tests/strings/str_prefix_remove.phpt new file mode 100644 index 0000000000000..3a8c3f5fd6f17 --- /dev/null +++ b/ext/standard/tests/strings/str_prefix_remove.phpt @@ -0,0 +1,64 @@ +--TEST-- +Test str_prefix_remove() function +--FILE-- + +--EXPECTF-- +*** Testing str_prefix_remove() : various strings *** +string(9) "MiddleEnd" +string(18) "BeginningMiddleEnd" +string(18) "BeginningMiddleEnd" +string(0) "" +string(18) "BeginningMiddleEnd" +string(18) "BeginningMiddleEnd" +string(0) "" +string(0) "" +string(18) "BeginningMiddleEnd" +string(1) "%0" +string(0) "" +string(1) "a" +string(1) "a" +string(3) "b%0a" +string(3) "b%0a" +string(1) "a" +string(1) "a" diff --git a/ext/standard/tests/strings/str_prefix_replace.phpt b/ext/standard/tests/strings/str_prefix_replace.phpt new file mode 100644 index 0000000000000..69030df3839ed --- /dev/null +++ b/ext/standard/tests/strings/str_prefix_replace.phpt @@ -0,0 +1,66 @@ +--TEST-- +Test str_prefix_replace() function +--FILE-- + +--EXPECTF-- +*** Testing str_prefix_replace() : various strings *** +string(14) "StartMiddleEnd" +string(18) "BeginningMiddleEnd" +string(9) "MiddleEnd" +string(21) "NewBeginningMiddleEnd" +string(19) "https://example.com" +string(8) "/opt/bin" +string(2) "ab" +string(8) "replaced" +string(0) "" +string(18) "BeginningMiddleEnd" +string(2) "ba" +string(2) "%0a" +string(3) "dab" +string(4) "%0dab" +string(3) "b%0a" +string(5) "newst" diff --git a/ext/standard/tests/strings/str_suffix_ensure.phpt b/ext/standard/tests/strings/str_suffix_ensure.phpt new file mode 100644 index 0000000000000..c1376e5cc7b68 --- /dev/null +++ b/ext/standard/tests/strings/str_suffix_ensure.phpt @@ -0,0 +1,64 @@ +--TEST-- +Test str_suffix_ensure() function +--FILE-- + +--EXPECTF-- +*** Testing str_suffix_ensure() : various strings *** +string(21) "BeginningMiddleEnding" +string(18) "BeginningMiddleEnd" +string(18) "BeginningMiddleEnd" +string(6) "suffix" +string(0) "" +string(1) " " +string(4) "aabc" +string(4) "test" +string(19) "BeginningMiddleEnd%0" +string(1) "%0" +string(1) "%0" +string(2) "a%0" +string(2) "a%0" +string(4) "ab%0c" +string(5) "ab%0%0c" +string(6) "b%0ad%0a" +string(6) "b%0az%0a" diff --git a/ext/standard/tests/strings/str_suffix_remove.phpt b/ext/standard/tests/strings/str_suffix_remove.phpt new file mode 100644 index 0000000000000..6178e0d3581bf --- /dev/null +++ b/ext/standard/tests/strings/str_suffix_remove.phpt @@ -0,0 +1,64 @@ +--TEST-- +Test str_suffix_remove() function +--FILE-- + +--EXPECTF-- +*** Testing str_suffix_remove() : various strings *** +string(15) "beginningMiddle" +string(18) "beginningMiddleEnd" +string(18) "beginningMiddleEnd" +string(0) "" +string(18) "beginningMiddleEnd" +string(18) "beginningMiddleEnd" +string(0) "" +string(0) "" +string(18) "beginningMiddleEnd" +string(1) "%0" +string(0) "" +string(1) "a" +string(1) "a" +string(3) "a%0b" +string(3) "a%0b" +string(1) "a" +string(1) "a" diff --git a/ext/standard/tests/strings/str_suffix_replace.phpt b/ext/standard/tests/strings/str_suffix_replace.phpt new file mode 100644 index 0000000000000..6ec6e93b0ee45 --- /dev/null +++ b/ext/standard/tests/strings/str_suffix_replace.phpt @@ -0,0 +1,66 @@ +--TEST-- +Test str_suffix_replace() function +--FILE-- + +--EXPECTF-- +*** Testing str_suffix_replace() : various strings *** +string(21) "BeginningMiddleFinish" +string(18) "BeginningMiddleEnd" +string(15) "BeginningMiddle" +string(21) "BeginningMiddleEndNew" +string(15) "file.backup.txt" +string(11) "document.md" +string(2) "ab" +string(8) "replaced" +string(0) "" +string(18) "BeginningMiddleEnd" +string(2) "ab" +string(2) "a%0" +string(3) "abd" +string(4) "ab%0d" +string(3) "a%0b" +string(5) "tenew" From e004c00dce65883228a45c88f80eba1899a9bbb3 Mon Sep 17 00:00:00 2001 From: Carlos Granados Date: Thu, 22 Jan 2026 19:16:10 +0100 Subject: [PATCH 2/2] Invert the order of parameters for remove and ensure functions --- ext/standard/basic_functions.stub.php | 8 +++--- ext/standard/basic_functions_arginfo.h | 6 ++-- ext/standard/string.c | 8 +++--- .../tests/strings/str_prefix_ensure.phpt | 28 +++++++++---------- .../tests/strings/str_prefix_remove.phpt | 28 +++++++++---------- .../tests/strings/str_suffix_ensure.phpt | 28 +++++++++---------- .../tests/strings/str_suffix_remove.phpt | 28 +++++++++---------- 7 files changed, 67 insertions(+), 67 deletions(-) diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index dbe4f78ad6798..114bb50be1971 100644 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2433,13 +2433,13 @@ function str_ends_with(string $haystack, string $needle): bool {} * @compile-time-eval * @refcount 1 */ -function str_prefix_ensure(string $prefix, string $subject): string {} +function str_prefix_ensure(string $subject, string $prefix): string {} /** * @compile-time-eval * @refcount 1 */ -function str_prefix_remove(string $prefix, string $subject): string {} +function str_prefix_remove(string $subject, string $prefix): string {} /** * @compile-time-eval @@ -2451,13 +2451,13 @@ function str_prefix_replace(string $prefix, string $replace, string $subject): s * @compile-time-eval * @refcount 1 */ -function str_suffix_ensure(string $suffix, string $subject): string {} +function str_suffix_ensure(string $subject, string $suffix): string {} /** * @compile-time-eval * @refcount 1 */ -function str_suffix_remove(string $suffix, string $subject): string {} +function str_suffix_remove(string $subject, string $suffix): string {} /** * @compile-time-eval diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index d49d442b1ec53..900ce2954bf2d 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit basic_functions.stub.php instead. - * Stub hash: ed8b640a6ea3d5fcb1a3c571bfe98c794e6448b4 */ + * Stub hash: 209b67970308b916c3c1c3fc717408275efef73e */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -929,8 +929,8 @@ ZEND_END_ARG_INFO() #define arginfo_str_ends_with arginfo_str_contains ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_prefix_ensure, 0, 2, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, prefix, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_str_prefix_remove arginfo_str_prefix_ensure @@ -942,8 +942,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_prefix_replace, 0, 3, IS_STR ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_str_suffix_ensure, 0, 2, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, suffix, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, suffix, IS_STRING, 0) ZEND_END_ARG_INFO() #define arginfo_str_suffix_remove arginfo_str_suffix_ensure diff --git a/ext/standard/string.c b/ext/standard/string.c index d9c79bdfe22b5..295b5a538b00b 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1895,8 +1895,8 @@ PHP_FUNCTION(str_prefix_ensure) zend_string *subject, *prefix; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR(prefix) Z_PARAM_STR(subject) + Z_PARAM_STR(prefix) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(prefix) == 0) { @@ -1922,8 +1922,8 @@ PHP_FUNCTION(str_prefix_remove) zend_string *subject, *prefix; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR(prefix) Z_PARAM_STR(subject) + Z_PARAM_STR(prefix) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(prefix) > ZSTR_LEN(subject)) { @@ -1972,8 +1972,8 @@ PHP_FUNCTION(str_suffix_ensure) zend_string *subject, *suffix; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR(suffix) Z_PARAM_STR(subject) + Z_PARAM_STR(suffix) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(suffix) == 0) { @@ -2001,8 +2001,8 @@ PHP_FUNCTION(str_suffix_remove) zend_string *subject, *suffix; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR(suffix) Z_PARAM_STR(subject) + Z_PARAM_STR(suffix) ZEND_PARSE_PARAMETERS_END(); if (ZSTR_LEN(suffix) > ZSTR_LEN(subject)) { diff --git a/ext/standard/tests/strings/str_prefix_ensure.phpt b/ext/standard/tests/strings/str_prefix_ensure.phpt index 5492ff7176dcc..a4804dc83dbca 100644 --- a/ext/standard/tests/strings/str_prefix_ensure.phpt +++ b/ext/standard/tests/strings/str_prefix_ensure.phpt @@ -8,39 +8,39 @@ echo "*** Testing str_prefix_ensure() : various strings ***\n"; $testStr = "BeginningMiddleEnd"; // Does not start with prefix - should be added -var_dump(str_prefix_ensure("The", $testStr)); +var_dump(str_prefix_ensure($testStr, "The")); // Already starts with prefix - should return original -var_dump(str_prefix_ensure("Beginning", $testStr)); +var_dump(str_prefix_ensure($testStr, "Beginning")); // Empty prefix - should return original -var_dump(str_prefix_ensure("", $testStr)); +var_dump(str_prefix_ensure($testStr, "")); // Empty source - should add prefix -var_dump(str_prefix_ensure("prefix", "")); +var_dump(str_prefix_ensure("", "prefix")); // Both empty strings var_dump(str_prefix_ensure("", "")); // Add prefix to empty string with space -var_dump(str_prefix_ensure(" ", "")); +var_dump(str_prefix_ensure("", " ")); // Source shorter than prefix but doesn't start with it -var_dump(str_prefix_ensure("abc", "a")); +var_dump(str_prefix_ensure("a", "abc")); // Source equals prefix - should return original var_dump(str_prefix_ensure("test", "test")); // Null byte handling -var_dump(str_prefix_ensure("\x00", $testStr)); -var_dump(str_prefix_ensure("", "\x00")); +var_dump(str_prefix_ensure($testStr, "\x00")); +var_dump(str_prefix_ensure("\x00", "")); var_dump(str_prefix_ensure("\x00", "\x00")); -var_dump(str_prefix_ensure("\x00", "\x00a")); -var_dump(str_prefix_ensure("\x00", "a")); -var_dump(str_prefix_ensure("\x00ab", "c\x00ab")); -var_dump(str_prefix_ensure("c\x00", "\x00ab")); -var_dump(str_prefix_ensure("a\x00d", "a\x00b")); -var_dump(str_prefix_ensure("a\x00z", "a\x00b")); +var_dump(str_prefix_ensure("\x00a", "\x00")); +var_dump(str_prefix_ensure("a", "\x00")); +var_dump(str_prefix_ensure("c\x00ab", "\x00ab")); +var_dump(str_prefix_ensure("\x00ab", "c\x00")); +var_dump(str_prefix_ensure("a\x00b", "a\x00d")); +var_dump(str_prefix_ensure("a\x00b", "a\x00z")); ?> --EXPECTF-- diff --git a/ext/standard/tests/strings/str_prefix_remove.phpt b/ext/standard/tests/strings/str_prefix_remove.phpt index 3a8c3f5fd6f17..03748de3c06a0 100644 --- a/ext/standard/tests/strings/str_prefix_remove.phpt +++ b/ext/standard/tests/strings/str_prefix_remove.phpt @@ -8,39 +8,39 @@ echo "*** Testing str_prefix_remove() : various strings ***\n"; $testStr = "BeginningMiddleEnd"; // Matching prefix - should be removed -var_dump(str_prefix_remove("Beginning", $testStr)); +var_dump(str_prefix_remove($testStr, "Beginning")); // Non-matching prefix (case sensitive) - should return original -var_dump(str_prefix_remove("beginning", $testStr)); +var_dump(str_prefix_remove($testStr, "beginning")); // Partial match but not at start - should return original -var_dump(str_prefix_remove("Middle", $testStr)); +var_dump(str_prefix_remove($testStr, "Middle")); // Remove entire string var_dump(str_prefix_remove($testStr, $testStr)); // Prefix longer than source - should return original -var_dump(str_prefix_remove($testStr.$testStr, $testStr)); +var_dump(str_prefix_remove($testStr, $testStr.$testStr)); // Empty prefix - should return original -var_dump(str_prefix_remove("", $testStr)); +var_dump(str_prefix_remove($testStr, "")); // Both empty strings var_dump(str_prefix_remove("", "")); // Empty source, non-empty prefix -var_dump(str_prefix_remove(" ", "")); +var_dump(str_prefix_remove("", " ")); // Null byte handling -var_dump(str_prefix_remove("\x00", $testStr)); -var_dump(str_prefix_remove("", "\x00")); +var_dump(str_prefix_remove($testStr, "\x00")); +var_dump(str_prefix_remove("\x00", "")); var_dump(str_prefix_remove("\x00", "\x00")); -var_dump(str_prefix_remove("\x00", "\x00a")); -var_dump(str_prefix_remove("\x00bc", "\x00bca")); -var_dump(str_prefix_remove("d\x00a", "b\x00a")); -var_dump(str_prefix_remove("z\x00a", "b\x00a")); -var_dump(str_prefix_remove("a\x00", "a")); -var_dump(str_prefix_remove("\x00a", "a")); +var_dump(str_prefix_remove("\x00a", "\x00")); +var_dump(str_prefix_remove("\x00bca", "\x00bc")); +var_dump(str_prefix_remove("b\x00a", "d\x00a")); +var_dump(str_prefix_remove("b\x00a", "z\x00a")); +var_dump(str_prefix_remove("a", "a\x00")); +var_dump(str_prefix_remove("a", "\x00a")); ?> --EXPECTF-- diff --git a/ext/standard/tests/strings/str_suffix_ensure.phpt b/ext/standard/tests/strings/str_suffix_ensure.phpt index c1376e5cc7b68..6f9db9ff4da4a 100644 --- a/ext/standard/tests/strings/str_suffix_ensure.phpt +++ b/ext/standard/tests/strings/str_suffix_ensure.phpt @@ -8,39 +8,39 @@ echo "*** Testing str_suffix_ensure() : various strings ***\n"; $testStr = "BeginningMiddleEnd"; // Does not end with suffix - should be added -var_dump(str_suffix_ensure("ing", $testStr)); +var_dump(str_suffix_ensure($testStr, "ing")); // Already ends with suffix - should return original -var_dump(str_suffix_ensure("End", $testStr)); +var_dump(str_suffix_ensure($testStr, "End")); // Empty suffix - should return original -var_dump(str_suffix_ensure("", $testStr)); +var_dump(str_suffix_ensure($testStr, "")); // Empty source - should add suffix -var_dump(str_suffix_ensure("suffix", "")); +var_dump(str_suffix_ensure("", "suffix")); // Both empty strings var_dump(str_suffix_ensure("", "")); // Add suffix to empty string with space -var_dump(str_suffix_ensure(" ", "")); +var_dump(str_suffix_ensure("", " ")); // Source shorter than suffix but doesn't end with it -var_dump(str_suffix_ensure("abc", "a")); +var_dump(str_suffix_ensure("a", "abc")); // Source equals suffix - should return original var_dump(str_suffix_ensure("test", "test")); // Null byte handling -var_dump(str_suffix_ensure("\x00", $testStr)); -var_dump(str_suffix_ensure("", "\x00")); +var_dump(str_suffix_ensure($testStr, "\x00")); +var_dump(str_suffix_ensure("\x00", "")); var_dump(str_suffix_ensure("\x00", "\x00")); -var_dump(str_suffix_ensure("\x00", "a\x00")); -var_dump(str_suffix_ensure("\x00", "a")); -var_dump(str_suffix_ensure("\x00c", "ab\x00c")); -var_dump(str_suffix_ensure("\x00c", "ab\x00")); -var_dump(str_suffix_ensure("d\x00a", "b\x00a")); -var_dump(str_suffix_ensure("z\x00a", "b\x00a")); +var_dump(str_suffix_ensure("a\x00", "\x00")); +var_dump(str_suffix_ensure("a", "\x00")); +var_dump(str_suffix_ensure("ab\x00c", "\x00c")); +var_dump(str_suffix_ensure("ab\x00", "\x00c")); +var_dump(str_suffix_ensure("b\x00a", "d\x00a")); +var_dump(str_suffix_ensure("b\x00a", "z\x00a")); ?> --EXPECTF-- diff --git a/ext/standard/tests/strings/str_suffix_remove.phpt b/ext/standard/tests/strings/str_suffix_remove.phpt index 6178e0d3581bf..a35d7855474b2 100644 --- a/ext/standard/tests/strings/str_suffix_remove.phpt +++ b/ext/standard/tests/strings/str_suffix_remove.phpt @@ -8,39 +8,39 @@ echo "*** Testing str_suffix_remove() : various strings ***\n"; $testStr = "beginningMiddleEnd"; // Matching suffix - should be removed -var_dump(str_suffix_remove("End", $testStr)); +var_dump(str_suffix_remove($testStr, "End")); // Non-matching suffix (case sensitive) - should return original -var_dump(str_suffix_remove("end", $testStr)); +var_dump(str_suffix_remove($testStr, "end")); // Partial match but not at end - should return original -var_dump(str_suffix_remove("en", $testStr)); +var_dump(str_suffix_remove($testStr, "en")); // Remove entire string var_dump(str_suffix_remove($testStr, $testStr)); // Suffix longer than source - should return original -var_dump(str_suffix_remove($testStr.$testStr, $testStr)); +var_dump(str_suffix_remove($testStr, $testStr.$testStr)); // Empty suffix - should return original -var_dump(str_suffix_remove("", $testStr)); +var_dump(str_suffix_remove($testStr, "")); // Both empty strings var_dump(str_suffix_remove("", "")); // Empty source, non-empty suffix -var_dump(str_suffix_remove(" ", "")); +var_dump(str_suffix_remove("", " ")); // Null byte handling -var_dump(str_suffix_remove("\x00", $testStr)); -var_dump(str_suffix_remove("", "\x00")); +var_dump(str_suffix_remove($testStr, "\x00")); +var_dump(str_suffix_remove("\x00", "")); var_dump(str_suffix_remove("\x00", "\x00")); -var_dump(str_suffix_remove("\x00", "a\x00")); -var_dump(str_suffix_remove("b\x00c", "ab\x00c")); -var_dump(str_suffix_remove("d\x00b", "a\x00b")); -var_dump(str_suffix_remove("a\x00z", "a\x00b")); -var_dump(str_suffix_remove("\x00a", "a")); -var_dump(str_suffix_remove("a\x00", "a")); +var_dump(str_suffix_remove("a\x00", "\x00")); +var_dump(str_suffix_remove("ab\x00c", "b\x00c")); +var_dump(str_suffix_remove("a\x00b", "d\x00b")); +var_dump(str_suffix_remove("a\x00b", "a\x00z")); +var_dump(str_suffix_remove("a", "\x00a")); +var_dump(str_suffix_remove("a", "a\x00")); ?> --EXPECTF--