Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize strcspn #67

Closed
wants to merge 2 commits into from
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
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ PHP 8.4 UPGRADE NOTES
. round() now validates the value of the $mode parameter and throws a ValueError
for invalid modes. Previously invalid modes would have been interpreted as
PHP_ROUND_HALF_UP.
. strcspn() with empty $characters now returns the length of the string instead
of incorrectly stopping at the first NUL character. See GH-12592.

- XML:
. The xml_set_*_handler() functions now declare and check for an effective
Expand Down
29 changes: 11 additions & 18 deletions ext/standard/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -1596,16 +1596,15 @@ PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
}
/* }}} */

/* {{{ php_strspn */
PHPAPI size_t php_strspn(const char *haystack, const char *characters, const char *haystack_end, const char *characters_end)
static size_t php_strspn_strcspn_common(const char *haystack, const char *characters, const char *haystack_end, const char *characters_end, bool must_match)
{
/* Fast path for short strings.
* The table lookup cannot be faster in this case because we not only have to compare, but also build the table.
* We only compare in this case.
* Empirically tested that the table lookup approach is only beneficial if characters is longer than 1 character. */
if (characters_end - characters == 1) {
const char *ptr = haystack;
while (ptr < haystack_end && *ptr == *characters) {
while (ptr < haystack_end && (*ptr == *characters) == must_match) {
ptr++;
}
return ptr - haystack;
Expand All @@ -1626,30 +1625,24 @@ PHPAPI size_t php_strspn(const char *haystack, const char *characters, const cha
}

const char *ptr = haystack;
while (ptr < haystack_end && table[(unsigned char) *ptr]) {
while (ptr < haystack_end && table[(unsigned char) *ptr] == must_match) {
ptr++;
}

return ptr - haystack;
}

/* {{{ php_strspn */
PHPAPI size_t php_strspn(const char *haystack, const char *characters, const char *haystack_end, const char *characters_end)
{
return php_strspn_strcspn_common(haystack, characters, haystack_end, characters_end, true);
}
/* }}} */

/* {{{ php_strcspn */
PHPAPI size_t php_strcspn(const char *s1, const char *s2, const char *s1_end, const char *s2_end)
PHPAPI size_t php_strcspn(const char *haystack, const char *characters, const char *haystack_end, const char *characters_end)
{
const char *p, *spanp;
char c = *s1;

for (p = s1;;) {
spanp = s2;
do {
if (*spanp == c || p == s1_end) {
return p - s1;
}
} while (spanp++ < (s2_end - 1));
c = *++p;
}
/* NOTREACHED */
return php_strspn_strcspn_common(haystack, characters, haystack_end, characters_end, false);
}
/* }}} */

Expand Down
2 changes: 1 addition & 1 deletion ext/standard/tests/strings/bug39032.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ echo "Done\n";
?>
--EXPECT--
int(1)
int(0)
int(1)
int(1)
int(1)
Done
28 changes: 14 additions & 14 deletions ext/standard/tests/strings/strcspn_variation10.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ int(21)
int(16)

-- Itearation 9 --
int(5)
int(5)
int(12)
int(12)
int(2)
int(2)
int(12)
Expand All @@ -180,8 +180,8 @@ int(16)
int(5)

-- Itearation 11 --
int(0)
int(0)
int(2)
int(2)
int(2)
int(2)
int(2)
Expand All @@ -192,8 +192,8 @@ int(2)
int(2)

-- Itearation 12 --
int(0)
int(0)
int(13)
int(13)
int(3)
int(3)
int(13)
Expand All @@ -204,8 +204,8 @@ int(13)
int(13)

-- Itearation 13 --
int(0)
int(0)
int(14)
int(14)
int(3)
int(3)
int(14)
Expand All @@ -216,8 +216,8 @@ int(14)
int(6)

-- Itearation 14 --
int(5)
int(5)
int(11)
int(11)
int(2)
int(2)
int(11)
Expand All @@ -228,8 +228,8 @@ int(11)
int(11)

-- Itearation 15 --
int(5)
int(5)
int(11)
int(11)
int(2)
int(2)
int(11)
Expand All @@ -240,8 +240,8 @@ int(11)
int(11)

-- Itearation 16 --
int(5)
int(5)
int(14)
int(14)
int(2)
int(2)
int(14)
Expand Down
120 changes: 60 additions & 60 deletions ext/standard/tests/strings/strcspn_variation11.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -650,20 +650,20 @@ int(0)
int(16)

-- Iteration 9 --
int(5)
int(4)
int(3)
int(12)
int(11)
int(10)
int(1)
int(2)
int(0)
int(5)
int(5)
int(4)
int(3)
int(12)
int(12)
int(11)
int(10)
int(1)
int(2)
int(0)
int(5)
int(12)
int(2)
int(1)
int(0)
Expand Down Expand Up @@ -794,20 +794,20 @@ int(0)
int(5)

-- Iteration 11 --
int(2)
int(1)
int(0)
int(1)
int(2)
int(0)
int(2)
int(2)
int(1)
int(0)
int(1)
int(2)
int(0)
int(0)
int(0)
int(0)
int(0)
int(0)
int(0)
int(0)
int(0)
int(0)
int(0)
int(2)
int(2)
int(1)
int(0)
Expand Down Expand Up @@ -866,20 +866,20 @@ int(0)
int(2)

-- Iteration 12 --
int(0)
int(5)
int(4)
int(0)
int(13)
int(12)
int(11)
int(1)
int(2)
int(0)
int(0)
int(0)
int(5)
int(4)
int(0)
int(13)
int(13)
int(12)
int(11)
int(1)
int(2)
int(0)
int(0)
int(13)
int(3)
int(2)
int(1)
Expand Down Expand Up @@ -938,20 +938,20 @@ int(0)
int(13)

-- Iteration 13 --
int(0)
int(14)
int(13)
int(12)
int(11)
int(0)
int(1)
int(2)
int(0)
int(0)
int(0)
int(14)
int(14)
int(13)
int(12)
int(11)
int(0)
int(1)
int(2)
int(0)
int(0)
int(14)
int(3)
int(2)
int(1)
Expand Down Expand Up @@ -1010,20 +1010,20 @@ int(0)
int(6)

-- Iteration 14 --
int(5)
int(4)
int(3)
int(11)
int(10)
int(9)
int(1)
int(2)
int(0)
int(5)
int(5)
int(4)
int(3)
int(11)
int(11)
int(10)
int(9)
int(1)
int(2)
int(0)
int(5)
int(11)
int(2)
int(1)
int(0)
Expand Down Expand Up @@ -1082,20 +1082,20 @@ int(0)
int(11)

-- Iteration 15 --
int(5)
int(4)
int(3)
int(11)
int(10)
int(9)
int(1)
int(2)
int(0)
int(5)
int(5)
int(4)
int(3)
int(11)
int(11)
int(10)
int(9)
int(1)
int(2)
int(0)
int(5)
int(11)
int(2)
int(1)
int(0)
Expand Down Expand Up @@ -1154,20 +1154,20 @@ int(0)
int(11)

-- Iteration 16 --
int(5)
int(4)
int(3)
int(14)
int(13)
int(12)
int(1)
int(2)
int(0)
int(5)
int(5)
int(4)
int(3)
int(14)
int(14)
int(13)
int(12)
int(1)
int(2)
int(0)
int(5)
int(14)
int(2)
int(1)
int(0)
Expand Down
Loading