Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ext/standard/basic_functions.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
121 changes: 121 additions & 0 deletions ext/standard/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
25 changes: 25 additions & 0 deletions tests/strings/subistring.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
subistring() function - unit tests for subistring()
--FILE--
<?php
$testStr = "The CAT sat on the Mat";
var_dump(subistring($testStr, "sat on the", ""));
var_dump(subistring($testStr, "The", "sat"));
var_dump(subistring($testStr, "The", "dog"));
var_dump(subistring($testStr, "T", "e"));
var_dump(subistring($testStr, "mat", "The"));
var_dump(subistring($testStr, "the", "sat"));
var_dump(subistring($testStr, " cat ", " on "));
var_dump(subistring($testStr, "", ""));
var_dump(subistring($testStr, "", "SAT"));
?>
--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"
25 changes: 25 additions & 0 deletions tests/strings/substring.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
substring() function - unit tests for substring()
--FILE--
<?php
$testStr = "The cat sat on the mat";
var_dump(substring($testStr, "sat on the", ""));
var_dump(substring($testStr, "The", "sat"));
var_dump(substring($testStr, "The", "dog"));
var_dump(substring($testStr, "T", "e"));
var_dump(substring($testStr, "mat", "The"));
var_dump(substring($testStr, "the", "sat"));
var_dump(substring($testStr, " cat ", " on "));
var_dump(substring($testStr, "", ""));
var_dump(substring($testStr, "", "sat"));
?>
--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"