Skip to content

Commit 9a973a3

Browse files
authored
Optimize strcspn (#12594)
1 parent bbe1222 commit 9a973a3

File tree

7 files changed

+198
-203
lines changed

7 files changed

+198
-203
lines changed

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ PHP 8.4 UPGRADE NOTES
4848
. round() now validates the value of the $mode parameter and throws a ValueError
4949
for invalid modes. Previously invalid modes would have been interpreted as
5050
PHP_ROUND_HALF_UP.
51+
. strcspn() with empty $characters now returns the length of the string instead
52+
of incorrectly stopping at the first NUL character. See GH-12592.
5153

5254
- XML:
5355
. The xml_set_*_handler() functions now declare and check for an effective

ext/standard/string.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,16 +1596,15 @@ PHPAPI char *php_stristr(char *s, char *t, size_t s_len, size_t t_len)
15961596
}
15971597
/* }}} */
15981598

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

16281627
const char *ptr = haystack;
1629-
while (ptr < haystack_end && table[(unsigned char) *ptr]) {
1628+
while (ptr < haystack_end && table[(unsigned char) *ptr] == must_match) {
16301629
ptr++;
16311630
}
16321631

16331632
return ptr - haystack;
16341633
}
1634+
1635+
/* {{{ php_strspn */
1636+
PHPAPI size_t php_strspn(const char *haystack, const char *characters, const char *haystack_end, const char *characters_end)
1637+
{
1638+
return php_strspn_strcspn_common(haystack, characters, haystack_end, characters_end, true);
1639+
}
16351640
/* }}} */
16361641

16371642
/* {{{ php_strcspn */
1638-
PHPAPI size_t php_strcspn(const char *s1, const char *s2, const char *s1_end, const char *s2_end)
1643+
PHPAPI size_t php_strcspn(const char *haystack, const char *characters, const char *haystack_end, const char *characters_end)
16391644
{
1640-
const char *p, *spanp;
1641-
char c = *s1;
1642-
1643-
for (p = s1;;) {
1644-
spanp = s2;
1645-
do {
1646-
if (*spanp == c || p == s1_end) {
1647-
return p - s1;
1648-
}
1649-
} while (spanp++ < (s2_end - 1));
1650-
c = *++p;
1651-
}
1652-
/* NOTREACHED */
1645+
return php_strspn_strcspn_common(haystack, characters, haystack_end, characters_end, false);
16531646
}
16541647
/* }}} */
16551648

ext/standard/tests/strings/bug39032.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ echo "Done\n";
1212
?>
1313
--EXPECT--
1414
int(1)
15-
int(0)
15+
int(1)
1616
int(1)
1717
int(1)
1818
Done

ext/standard/tests/strings/strcspn_variation10.phpt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,8 @@ int(21)
156156
int(16)
157157

158158
-- Itearation 9 --
159-
int(5)
160-
int(5)
159+
int(12)
160+
int(12)
161161
int(2)
162162
int(2)
163163
int(12)
@@ -180,8 +180,8 @@ int(16)
180180
int(5)
181181

182182
-- Itearation 11 --
183-
int(0)
184-
int(0)
183+
int(2)
184+
int(2)
185185
int(2)
186186
int(2)
187187
int(2)
@@ -192,8 +192,8 @@ int(2)
192192
int(2)
193193

194194
-- Itearation 12 --
195-
int(0)
196-
int(0)
195+
int(13)
196+
int(13)
197197
int(3)
198198
int(3)
199199
int(13)
@@ -204,8 +204,8 @@ int(13)
204204
int(13)
205205

206206
-- Itearation 13 --
207-
int(0)
208-
int(0)
207+
int(14)
208+
int(14)
209209
int(3)
210210
int(3)
211211
int(14)
@@ -216,8 +216,8 @@ int(14)
216216
int(6)
217217

218218
-- Itearation 14 --
219-
int(5)
220-
int(5)
219+
int(11)
220+
int(11)
221221
int(2)
222222
int(2)
223223
int(11)
@@ -228,8 +228,8 @@ int(11)
228228
int(11)
229229

230230
-- Itearation 15 --
231-
int(5)
232-
int(5)
231+
int(11)
232+
int(11)
233233
int(2)
234234
int(2)
235235
int(11)
@@ -240,8 +240,8 @@ int(11)
240240
int(11)
241241

242242
-- Itearation 16 --
243-
int(5)
244-
int(5)
243+
int(14)
244+
int(14)
245245
int(2)
246246
int(2)
247247
int(14)

ext/standard/tests/strings/strcspn_variation11.phpt

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -650,20 +650,20 @@ int(0)
650650
int(16)
651651

652652
-- Iteration 9 --
653-
int(5)
654-
int(4)
655-
int(3)
653+
int(12)
654+
int(11)
655+
int(10)
656656
int(1)
657657
int(2)
658658
int(0)
659-
int(5)
660-
int(5)
661-
int(4)
662-
int(3)
659+
int(12)
660+
int(12)
661+
int(11)
662+
int(10)
663663
int(1)
664664
int(2)
665665
int(0)
666-
int(5)
666+
int(12)
667667
int(2)
668668
int(1)
669669
int(0)
@@ -794,20 +794,20 @@ int(0)
794794
int(5)
795795

796796
-- Iteration 11 --
797+
int(2)
798+
int(1)
797799
int(0)
800+
int(1)
801+
int(2)
798802
int(0)
803+
int(2)
804+
int(2)
805+
int(1)
799806
int(0)
807+
int(1)
808+
int(2)
800809
int(0)
801-
int(0)
802-
int(0)
803-
int(0)
804-
int(0)
805-
int(0)
806-
int(0)
807-
int(0)
808-
int(0)
809-
int(0)
810-
int(0)
810+
int(2)
811811
int(2)
812812
int(1)
813813
int(0)
@@ -866,20 +866,20 @@ int(0)
866866
int(2)
867867

868868
-- Iteration 12 --
869-
int(0)
870-
int(5)
871-
int(4)
872-
int(0)
869+
int(13)
870+
int(12)
871+
int(11)
873872
int(1)
873+
int(2)
874874
int(0)
875-
int(0)
876-
int(0)
877-
int(5)
878-
int(4)
879-
int(0)
875+
int(13)
876+
int(13)
877+
int(12)
878+
int(11)
880879
int(1)
880+
int(2)
881881
int(0)
882-
int(0)
882+
int(13)
883883
int(3)
884884
int(2)
885885
int(1)
@@ -938,20 +938,20 @@ int(0)
938938
int(13)
939939

940940
-- Iteration 13 --
941-
int(0)
941+
int(14)
942+
int(13)
942943
int(12)
943-
int(11)
944-
int(0)
945944
int(1)
945+
int(2)
946946
int(0)
947-
int(0)
948-
int(0)
947+
int(14)
948+
int(14)
949+
int(13)
949950
int(12)
950-
int(11)
951-
int(0)
952951
int(1)
952+
int(2)
953953
int(0)
954-
int(0)
954+
int(14)
955955
int(3)
956956
int(2)
957957
int(1)
@@ -1010,20 +1010,20 @@ int(0)
10101010
int(6)
10111011

10121012
-- Iteration 14 --
1013-
int(5)
1014-
int(4)
1015-
int(3)
1013+
int(11)
1014+
int(10)
1015+
int(9)
10161016
int(1)
10171017
int(2)
10181018
int(0)
1019-
int(5)
1020-
int(5)
1021-
int(4)
1022-
int(3)
1019+
int(11)
1020+
int(11)
1021+
int(10)
1022+
int(9)
10231023
int(1)
10241024
int(2)
10251025
int(0)
1026-
int(5)
1026+
int(11)
10271027
int(2)
10281028
int(1)
10291029
int(0)
@@ -1082,20 +1082,20 @@ int(0)
10821082
int(11)
10831083

10841084
-- Iteration 15 --
1085-
int(5)
1086-
int(4)
1087-
int(3)
1085+
int(11)
1086+
int(10)
1087+
int(9)
10881088
int(1)
10891089
int(2)
10901090
int(0)
1091-
int(5)
1092-
int(5)
1093-
int(4)
1094-
int(3)
1091+
int(11)
1092+
int(11)
1093+
int(10)
1094+
int(9)
10951095
int(1)
10961096
int(2)
10971097
int(0)
1098-
int(5)
1098+
int(11)
10991099
int(2)
11001100
int(1)
11011101
int(0)
@@ -1154,20 +1154,20 @@ int(0)
11541154
int(11)
11551155

11561156
-- Iteration 16 --
1157-
int(5)
1158-
int(4)
1159-
int(3)
1157+
int(14)
1158+
int(13)
1159+
int(12)
11601160
int(1)
11611161
int(2)
11621162
int(0)
1163-
int(5)
1164-
int(5)
1165-
int(4)
1166-
int(3)
1163+
int(14)
1164+
int(14)
1165+
int(13)
1166+
int(12)
11671167
int(1)
11681168
int(2)
11691169
int(0)
1170-
int(5)
1170+
int(14)
11711171
int(2)
11721172
int(1)
11731173
int(0)

0 commit comments

Comments
 (0)