From 997b478203895a5a96a92e3f25ac89564eb4e9c1 Mon Sep 17 00:00:00 2001 From: AdsarAdam Date: Wed, 13 Jan 2021 10:27:53 +0000 Subject: [PATCH 1/2] Substring --- ext/standard/basic_functions.stub.php | 4 + ext/standard/string.c | 121 ++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 5d325515f7d1c..1d9b51d50abe3 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -599,6 +599,10 @@ function str_starts_with(string $haystack, string $needle): bool {} function str_ends_with(string $haystack, string $needle): bool {} +function substring(string $haystack, string $from, string $to): string {} + +function subistring(string $haystack, string $from, string $to): string {} + function chunk_split(string $string, int $length = 76, string $separator = "\r\n"): string {} function substr(string $string, int $offset, ?int $length = null): string {} diff --git a/ext/standard/string.c b/ext/standard/string.c index 8d0754347a0ac..2bec90fe95bc7 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2078,6 +2078,127 @@ PHP_FUNCTION(strrchr) } /* }}} */ + +/* {{{ Returns a portion of the string found between two strings */ +PHP_FUNCTION(substring) +{ + const char *found_from = NULL, *found_to = NULL; + zend_string *haystack, *from, *to, *string, *trim; + zend_long offset = 0, length; + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(haystack) + Z_PARAM_STR(from) + Z_PARAM_STR(to) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(from) > 0) { + found_from = (char*)php_memnstr(ZSTR_VAL(haystack), + ZSTR_VAL(from), ZSTR_LEN(from), + ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); + + if (!found_from) { + RETURN_EMPTY_STRING(); + } + + offset = found_from - ZSTR_VAL(haystack) + ZSTR_LEN(from); + + } + + if (ZSTR_LEN(to) > 0) { + found_to = (char*)php_memnstr(ZSTR_VAL(haystack) + offset, + ZSTR_VAL(to), ZSTR_LEN(to), + ZSTR_VAL(haystack) + ZSTR_LEN(haystack)); + + if (!found_to) { + RETURN_EMPTY_STRING(); + } + + length = found_to - ZSTR_VAL(haystack) - offset; + + } else { + length = ZSTR_LEN(haystack) - offset; + } + + string = zend_string_safe_alloc(1, length, 0, 0); + memcpy(ZSTR_VAL(string), ZSTR_VAL(haystack) + offset, length); + + trim = php_trim_int(string, NULL, 0, 3); + + if (ZSTR_LEN(trim) == 0) { + RETURN_EMPTY_STRING(); + } + + RETURN_NEW_STR(trim); + +} +/* }}} */ + + +/* {{{ Returns a portion of the string found between two strings */ +PHP_FUNCTION(subistring) +{ + const char *found_from = NULL, *found_to = NULL; + zend_string *haystack, *haystack_dup, *from, *to, *string, *trim; + zend_long offset = 0, length; + + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(haystack) + Z_PARAM_STR(from) + Z_PARAM_STR(to) + ZEND_PARSE_PARAMETERS_END(); + + haystack_dup = zend_string_safe_alloc(1, ZSTR_LEN(haystack), 0, 0); + memcpy(ZSTR_VAL(haystack_dup), ZSTR_VAL(haystack), ZSTR_LEN(haystack)); + + haystack_dup = php_string_tolower(haystack_dup); + + from = php_string_tolower(from); + to = php_string_tolower(to); + + if (ZSTR_LEN(from) > 0) { + found_from = (char*)php_memnstr(ZSTR_VAL(haystack_dup), + ZSTR_VAL(from), ZSTR_LEN(from), + ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack_dup)); + + if (!found_from) { + RETURN_EMPTY_STRING(); + } + + offset = found_from - ZSTR_VAL(haystack_dup) + ZSTR_LEN(from); + + } + + if (ZSTR_LEN(to) > 0) { + found_to = (char*)php_memnstr(ZSTR_VAL(haystack_dup) + offset, + ZSTR_VAL(to), ZSTR_LEN(to), + ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack_dup)); + + if (!found_to) { + RETURN_EMPTY_STRING(); + } + + length = found_to - ZSTR_VAL(haystack_dup) - offset; + + } else { + length = ZSTR_LEN(haystack_dup) - offset; + } + + string = zend_string_safe_alloc(1, length, 0, 0); + memcpy(ZSTR_VAL(string), ZSTR_VAL(haystack) + offset, length); + + trim = php_trim_int(string, NULL, 0, 3); + + if (ZSTR_LEN(trim) == 0) { + RETURN_EMPTY_STRING(); + } + + RETURN_NEW_STR(trim); + +} +/* }}} */ + + /* {{{ php_chunk_split */ static zend_string *php_chunk_split(const char *src, size_t srclen, const char *end, size_t endlen, size_t chunklen) { From 863babafbd6d9295c39388f2a7699757e4ac7f0b Mon Sep 17 00:00:00 2001 From: AdsarAdam Date: Wed, 13 Jan 2021 10:28:26 +0000 Subject: [PATCH 2/2] Substring --- tests/strings/subistring.phpt | 25 +++++++++++++++++++++++++ tests/strings/substring.phpt | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tests/strings/subistring.phpt create mode 100644 tests/strings/substring.phpt diff --git a/tests/strings/subistring.phpt b/tests/strings/subistring.phpt new file mode 100644 index 0000000000000..98eae08190068 --- /dev/null +++ b/tests/strings/subistring.phpt @@ -0,0 +1,25 @@ +--TEST-- +subistring() function - unit tests for subistring() +--FILE-- + +--EXPECT-- +string(3) "Mat" +string(3) "CAT" +string(0) "" +string(1) "h" +string(0) "" +string(3) "CAT" +string(3) "sat" +string(22) "The CAT sat on the Mat" +string(7) "The CAT" diff --git a/tests/strings/substring.phpt b/tests/strings/substring.phpt new file mode 100644 index 0000000000000..9e1da383d8e6c --- /dev/null +++ b/tests/strings/substring.phpt @@ -0,0 +1,25 @@ +--TEST-- +substring() function - unit tests for substring() +--FILE-- + +--EXPECT-- +string(3) "mat" +string(3) "cat" +string(0) "" +string(1) "h" +string(0) "" +string(0) "" +string(3) "sat" +string(22) "The cat sat on the mat" +string(7) "The cat"